3

I have a webservice project (old asmx technology) in which I have a class User. This class has a DateTime property that represents the birthdate of this user. Beside this class, I have another file with a partial class User. In this partial class, I add a property 'Age' which returns the age of the user:

public partial class User
{
    public DateTime Age
    {
        get { return DateTime.Now - this.Birthdate; }
    }
}

The reason that this is in a partial class is because the User class code is automatically generated from a config file, and I cannot add code to this class without it being removed every time the code is generated.

Now in my webservice I have a webmethod that returns a list of these Users which it gets from a database:

[WebMethod]
public List<User> GetUsers()
{
    return Database.LoadUsers();
}

Simple enough... Anyway, in a different project now, I add a Service Reference to this webservice. It generates the service client and a User class for me. The problem is: this User class does not contain the properties defined in the partial class (Age in this example)... It seems the webservice doesn't get this information.

Of course I can create a new partial User class and basically rewrite it in the second project, but I shouldn't have to, should I? Why doesn't the webservice recognize the partial class?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Nick Thissen
  • 1,802
  • 4
  • 27
  • 38

2 Answers2

3

Partial classes are not extension methods. They are compiled together into one class in each assembly. You have two options for what you want to do:

Option 1

Add the partial class you wrote as a link to the new project. It will be the same file, but linked into the new project. When you go to Add -> Existing Item, select the arrow by Open and choose "Add as Link".

Option 2

Create an extension method:

public static class DateExtensions
{
    public TimeSpan GetAge(this DateTime birthDate)
    {
        return DateTime.Now - birthDate;
    }
}

Then, just add a using statement for whatever namespace your extension class is in, and make sure the project/assembly is referenced, and you can call this:

// This is your BirthDate property that would come back and is DateTime
var birthDate = new SomeService().DoSomething().BirthDate;

var age = birthDate.GetAge();

Option 3

Create a separate project and put the service reference and partial in it. Reference the project (and the necessary framework references) from your using projects.

I have created an example for you to view/use on GitHub.

Chris Benard
  • 3,167
  • 2
  • 29
  • 35
  • Option 1 does not work, because the partial class is then no longer in the same project (and it cannot access the properties of the actual class). Option 2 only works for this simple example and is not really related to my problem, I can't use it for my actual project. If the partial class is compiled together in the assembly, then why does the webservice reference not see the properties in the partial class? They should be in the same class (compiled together!) after compilation?! – Nick Thissen Apr 03 '12 at 14:11
  • I understand option 2, but you're wrong on option 1. Adding as a link is the exact same as **copying** the source file into the new project, except there is only 1 single instance of the actual file, and if you change it in one place, it changes in all of them, since it's the same file. – Chris Benard Apr 03 '12 at 14:12
  • When you add the second service reference, you're not referencing an assembly. You're adding new source code into your new project. The proxy class is a separate file when you add a new reference, so you need to add your partial as a **link**. It won't be a copy, but a reference to the original location, but it will be compiled into both project assemblies. – Chris Benard Apr 03 '12 at 14:16
  • I do what Chris Bernard has done with option 1. Create a new file, and make sure the namespace is the same as the auto-generated User class. The class name must also be the same (which yours is, I mention this as help to others with the same problem). This file exists where my service code is. In the client project, I add this file as a link, and my client code now has those extra added properties. The nice thing about this method is that these extra properties are not necessarily transferred over the wire, amounting to bandwidth savings. – Derreck Dean Apr 03 '12 at 14:17
  • I might not understand properly, but what do I do if the User class in the webservice project and the (proxy) User class in the other project (where I add the service reference) are not in the same namespace? I can add the file as a link, fine, but I can't change the namespace cause that would change it in the original place too. Since the namespace for the proxy class is fixed (I guess? as its auto-generated...) I'd have to change the namespace to the original class?! – Nick Thissen Apr 03 '12 at 14:32
  • Just to clarify: the proxy User class must obviously be in the same namespace as the partial User class (linked via the original project), otherwise the partial class thingy doesn't work. But it isn't in the same namespace... It's a completely different project so how can it be?! – Nick Thissen Apr 03 '12 at 14:33
  • Namespaces aren't tied to projects. That's just a convention. You can set the namespace of your new service reference to match the namespace of your old service reference, and then it will match the namespace of your partial class. If you're having trouble with that, create a new project, put your **one** service reference and partial class in there, and then reference that project and use the service reference from there, having only one service reference and partial. – Chris Benard Apr 03 '12 at 14:35
  • @Nick Thissen, I have updated the answer with a third option, involving what I just talked about, with having a separate project for the service reference and putting your partial in there. Please grab that and see if it solves your issue. Please accept the answer if it solves your issue. Thanks. – Chris Benard Apr 03 '12 at 15:21
  • I've changed the namespace of the generated User class in the end to match the namespace output by the service reference proxy (didn't see how to change that). It's not very beautiful but it works. Thanks. – Nick Thissen Apr 03 '12 at 16:55
  • Great Nick, but do be aware, if you refresh your service reference (right click on it, update service reference) ever, your namespace will probably be reset to its original and you'll have to change it again. Option 3 may be worth the extra setup for how robust it is, but I'm glad you're up and running. – Chris Benard Apr 03 '12 at 17:11
0

If you must tightly couple your client to your service then you may be able to get the Service Reference to reuse the same types that are used by the service. Simply move the types in question to their own project and assembly, and reference that from both the client and server projects.

My hesitation is that this works with a WCF service, but I've never done it with an ASMX service.

John Saunders
  • 160,644
  • 26
  • 247
  • 397