我尝试调用一个名为Register的WebInvoke方法,该方法返回一个User对象并立即返回该对象。它看起来如下:
User Register(User user)
{
return user;
}
我不确定在调用http://localhost:8081/user/register时,Name和Namespace属性对DataContract属性的作用是什么?
我问的原因是因为我最初使用DataContract属性装饰了我的类,如下所示:
[DataContract]
public class User
{
// Properties
}
当我打开Fiddler并发送一个Post请求时,它说方法不允许,但当我将DataContract更改为:
[DataContract(Name="User", Namespace="")]
有效。
答案 0 :(得分:14)
除了其他答案之外,DataContract中的命名空间允许在不同的命名空间中使用两个相同名称的对象 - 即版本控制。
允许这两个对象作为WSDL中的不同属性存在,并且只要它们具有不同的名称空间,就会知道可反序列化的类型:
[DataContact(Namespace = "http://myservice/v1/thing")]
V1.Thing
[DataContact(Namespace = "http://myservice/v2/thing")]
V2.Thing
当然,它们需要存在于您的C#代码中以使其有效。或者,您也可以使用“名称”属性更改对象已知的名称。
[DataContact(Name = "Thing")]
V1.Thing
[DataContact(Name= = "newThing")]
V2.Thing
您可以在项目中更改类名称时使用此选项,但您需要支持使用“旧”名称的现有客户端。
总之,Name和Namespace属性控制在通过网络传输时对象的序列化和反序列化方式。设置它们时,您将控制客户端查看数据合同的方式。
答案 1 :(得分:10)
约翰的回答,IMO是正确的。
它以这种方式工作,因为当您发送SOAP消息时,元素需要进行命名空间限定,否则WCF不知道如何将SOAP反序列化为用户数据协定,因为命名空间不匹配。
在C#中,这两个对象是不同的,因为它们位于不同的名称空间......
namespace UserServices
{
public class User
{
public string FirstName { get; set; }
}
}
namespace TempuriServices
{
public class User
{
public string FirstName { get; set; }
}
}
XML / SOAP中的命名空间用于相同的目的,以确保对象来自相同的“body”/“company”/“organization”/“domain”等。
根据我的发现,当我构建SOAP服务时,我倾向于将所有数据协定,服务契约和绑定名称空间保留在同一名称空间中,例如: “http://mycompany.com/services/serviceName”
这里有一些很棒的资源...... 数据合同等价=> http://msdn.microsoft.com/en-us/library/ms734767.aspx 数据合同版本控制最佳实践=> http://msdn.microsoft.com/en-us/library/ms733832.aspx
希望这有帮助。
答案 2 :(得分:7)
这些属性控制WSDL中元素的名称空间和名称。代码中的重要部分是Namespace=""
:这将覆盖默认命名空间(http://tempuri.org)并将其值设置为空URL。
最后,User类将在WSDL中从http://tempuri.org/User重命名为User。
答案 3 :(得分:1)
除了其他答案之外,我还会尝试在此主题中添加我所知道的内容。 简而言之,它们都会覆盖[DataContract]和[DataMember](Name)的默认名称和命名空间,无论您提供给这些属性。 根据MS的DataContractAttribute.Namespace属性文档(它们被称为属性的属性,而不是属性),在“提示”部分,它指出link,“对于数据是成功传输后,数据协定中数据的名称在客户端和服务器中必须相同。默认情况下,Visual Basic项目为每个文件中定义的命名空间添加前缀(称为“根命名空间”,命名为在项目之后)。添加此前缀会导致客户端和服务器名称空间对于相同类型不同。解决方案是将Namespace属性设置为“”,或者显式设置数据协定名称空间这个性质。” 根据我的理解,对于DataContract属性能够序列化/反序列化数据,数据必须在客户端和服务器端都具有匹配的命名空间,在实际情况中可能永远不会出现这种情况。例如,如果以可读和合理的方式命名,则服务器端的数据可能位于名称类似于“NameOfTheSolution.Server.NameOfTheProject”的名称空间下,而在客户端,它可能类似于“ NameOfTheSolution.Client.NameOfTheProject“。由于DataContracts所在的命名空间不同,[DataContract]属性将无法序列化/反序列化客户端和服务器之间的数据。我不是肯定的,但这可能是它因为命名空间不匹配而在您的情况下说不允许的方法的原因。在命名空间不匹配的情况下,可以在使用[DataContract]属性时使用“Namespace”属性,并在任一侧(客户端/服务器)提供具有相同命名空间的类,尽管它们实际上位于不同的命名空间中。
[DataContract (Namespace = “Whatever you want, usually uri”)]
public class User
{}
就[DataContract]属性的'Name'属性而言,它会使用您为此属性提供的名称覆盖datacontract的名称。在DataMember属性的上下文中,它的一个用途是重载数据协定中的方法。 DataContract不允许两个具有相同名称的DataMember,因此在这种情况下,“Name”属性很有用。
答案 4 :(得分:0)
基于另一个问题并在:
我不知道名字和名字是什么 命名空间属性对 调用时的DataContract属性 http://localhost:8081/user/register 例如?
我建议您使用REST服务。当您在未将Namespace设置为空字符串的情况下调用服务时,您是否使用名称空间xmlns =“http://tempuri.org”定义了User XML?如果没有,你发送服务不同/未知“数据类型”,这可能是返回错误的原因。