简体   繁体   中英

Class constructor (from C# web service) won't auto-implement properties in C# MVC

I'm running two instances of VS2010 on my local machine. One instance is running my Web Service (written in C#). The other instance is running my MVC web app (also C#). The MVC web app has a reference to the web service. I can successfully invoke web service methods from within the MVC app.

In my web service is a PageNavigation class:

// PageNavigation.cs
using System;
using System.Collections.Generic;
using System.Text;

public class PageNavigation
{
    public string Page_Number { get; set; }
    public string Page_Count { get; set; }

    public PageNavigation()
    {
        Page_Number = "1";
        Page_Count = "2";
    }
}

By default, this should return an object with auto-implemented properties when I call the class constructor:

WebService.PageNavigation pageNavigation = new WebService.PageNavigation();

This works when constructing a PageNavigation object elsewhere in the web service.

pageNavigation.Page_Number
"1"
pageNavigation.Page_Count
"2"

However, running the same line of code on the MVC isn't giving the same result; the object's properties are all null values.

pageNavigation.Page_Number
null
pageNavigation.Page_Count
null

Is this the expected behavior? Is there a way to populate the properties with default values as intended? If more information is needed please let me know and I will update the question.

The service reference only sees the schema of your object, not business logic; in your case, your service reference just created a shell data type in the MVC application. When you create a service reference, it's actually creating another type with the same property names and types as the type defined in the service.

For your particular scenario (simply providing default property values and not more general business logic), you should be able to apply the [System.ComponentModel.DefaultValue] attribute to your properties in order for the class generator to recognize that these properties should be populated with a default value.

Incidentally, if the service reference were reusing existing types (if you had this type in a common library that was referenced both by the service and the application, for example), then your business logic would be intact.

An alternative would be to implement a factory pattern, whereby you call a function on the web service that instantiates (and optionally populates) the data object, then returns it to the client.

Yes, this is expected behaviour. The MVC site is not actually using your PageNavigation class. It is a simple copy (generated when you add the web service reference) containing of all the properties, but none of the methods, including the constructor.

You could work around this by refactoring your service so the entities are in a separate assembly and then you can reuse this assembly on the client as an option when you generate the proxy.

If you insist on using the same types between client and service, then on the "Advanced" tab of the "Add Service Reference" dialog, you can choose to reuse the types in your server assembly.

I would move that class out of the service and into a class library project referenced by the service and by the client.

And I wouldn't do this for such a small reason as default values. this violates SOA by coupling the service and the client. It will obviously not work for clients which are not running .NET.

What serializer are you using to deserialize the response from the server? Some of them (like the DataContractSerializer for example) do not call the default constructor.

The solution that you should use if you are in fact using DataContractSerializer is to use the OnDeserialized attribute like this:

using System.Runtime.Serialization;

public class PageNavigation
{
    public string Page_Number { get; set; }
    public string Page_Count { get; set; }

    public PageNavigation()
    {
        Init();
    }

    [OnDeserialize]
    void Init()
    {
        Page_Number = "1";
        Page_Count = "2";
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM