简体   繁体   English

类构造函数(来自C#Web服务)不会在C#MVC中自动实现属性

[英]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. 我正在本地计算机上运行VS2010的两个实例。 One instance is running my Web Service (written in C#). 一个实例正在运行我的Web服务(用C#编写)。 The other instance is running my MVC web app (also C#). 另一个实例正在运行我的MVC Web应用程序(也为C#)。 The MVC web app has a reference to the web service. MVC Web应用程序具有对该Web服务的引用。 I can successfully invoke web service methods from within the MVC app. 我可以从MVC应用程序中成功调用Web服务方法。

In my web service is a PageNavigation class: 在我的Web服务中是一个PageNavigation类:

// 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. 当在Web服务中的其他位置构造PageNavigation对象时,此方法有效。

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

However, running the same line of code on the MVC isn't giving the same result; 但是,在MVC上运行相同的代码行并不会得到相同的结果。 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. 在您的情况下,您的服务引用只是在MVC应用程序中创建了Shell数据类型。 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. 对于您的特定方案(仅提供默认属性值,而不是更通用的业务逻辑),应该可以将[System.ComponentModel.DefaultValue]属性应用于属性,以便类生成器识别出应该填充这些属性使用默认值。

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. 另一种选择是实现工厂模式,即您在Web服务上调用一个函数,该函数实例化(并可选地填充)数据对象,然后将其返回给客户端。

Yes, this is expected behaviour. 是的,这是预期的行为。 The MVC site is not actually using your PageNavigation class. MVC站点实际上并未使用您的PageNavigation类。 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. 它是一个简单的副本(添加Web服务引用时生成),包含所有属性,但不包含所有方法,包括构造函数。

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. 通过将服务和客户端耦合在一起,这违反了SOA。 It will obviously not work for clients which are not running .NET. 对于未运行.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. 其中一些(例如DataContractSerializer )不调用默认构造函数。

The solution that you should use if you are in fact using DataContractSerializer is to use the OnDeserialized attribute like this: 如果实际上使用的是DataContractSerializer ,则应使用的解决方案是使用OnDeserialized属性,如下所示:

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";
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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