17
votes

I tried calling a WebInvoke method called Register which returns takes in a User object and immediately just returns that object. It looks like the following:

User Register(User user)
{
    return user;
}

I am not sure what the Name and Namespace attributes do to the DataContract attribute when calling http://localhost:8081/user/register for example?

The reason I ask is because I initially had my class decorated with the DataContract attribute like this:

[DataContract]
public class User
{
   // Properties
}

When I opened up Fiddler, and sent a Post request, it said method not allowed, but when I changed DataContract to:

[DataContract(Name="User", Namespace="")]

It worked.

5

5 Answers

14
votes

In additional to the other answers, the Namespace in a DataContract allows for two objects of the same name in different namespaces - i.e. versioning.

These two objects are allowed to exist as different properties in a WSDL and will be known deserializable types provided they have different namespaces:

[DataContract(Namespace = "http://myservice/v1/thing")]
V1.Thing

[DataContract(Namespace = "http://myservice/v2/thing")]
V2.Thing

Of course, they need to exist in your C# code as well for it to be valid. Or, alternatively you can change the name that the objects are known by using the Name attribute for clarity.

[DataContract(Name = "Thing")]
V1.Thing

[DataContract(Name= = "newThing")]
V2.Thing

You might use this when the class' name has changed in your project, but you need to support existing clients that use the 'old' names.

In summary, the Name and Namespace properties control how your objects will be serialized and deserialized when transmitted over the wire. When you set them, you are controlling how the client will see your data contract.

10
votes

Johann's answer, IMO is the correct one.

It works this way because when you send SOAP messages, the elements need to be namespace qualified, otherwise the WCF doesnt know how to deserialize the SOAP into the User data contract because of the namespace mismatch.

In C#, these two objects are different because they are in different namespaces...

namespace UserServices
{
    public class User
    {
        public string FirstName { get; set; }
    }
}

namespace TempuriServices
{
    public class User
    {
        public string FirstName { get; set; }
    }
}

The Namespace in XML / SOAP serves the same purpose, to make sure the objects are from the same "body" / "company" / "organization" / "domain" etc.

From what I have found, when I build SOAP services, I tend to keep all of my data contracts, service contracts, and binding namespaces in the same namespace, e.g. "http://mycompany.com/services/serviceName"

here are some great resources... Data Contract Equivalence => http://msdn.microsoft.com/en-us/library/ms734767.aspx Data Contract Versioning Best Practices => http://msdn.microsoft.com/en-us/library/ms733832.aspx

Hope this helps.

7
votes

These properties control the namespace and name of the element in the WSDL. The important part in your code is the Namespace="": this will override the default namespace (http://tempuri.org) and set its value to an empty URL.

In the end, the User class will be renamed in the WSDL from http://tempuri.org/User to simply User.

1
votes

In addition to other answers, I will try to add what I know to this topic. In short, they both overwrite the default Name and Namespace of the [DataContract] and [DataMember] (Name) with whatever you supply to these properties. According to the MS’s documentation for DataContractAttribute.Namespace property (they are called properties of the attribute, not attribute), on the 'Tip' section it states link, "For the data to be successfully transmitted, the name of the data in a data contract must be the same in both the client and the server. Visual Basic projects, by default, add a prefix to the namespace defined in each file (called the “root namespace,” named after the project). Adding this prefix causes the client and server namespaces to be different for the same type. The solution is to set the Namespace property to “”, or to explicitly set the data contract namespace in this property." From what I have understood, for DataContract attribute to be able to serialize/deserialize the data, the data must have a matching namespace in both client and the server side, which might always not be the case in a real world situation. For instance, your data on the Server side, if named in a readable and sensible way, might be under the namespace that has a name something like "NameOfTheSolution.Server.NameOfTheProject," whereas on the client side, it could be something like "NameOfTheSolution.Client.NameOfTheProject." Due to different namespace the DataContracts are in, [DataContract] attribute won't be able serialize/deserialize the data between the client and server. I am not positive, but this could be the reason why it said method not allowed in your case, due to a mismatched namespace. In a situation where namespaces do not match, 'Namespace' property could be used while using the [DataContract] attribute and provide the class on the either side (client/server) with the same namespace, although they physically lay in different namespaces.

[DataContract (Namespace = “Whatever you want, usually uri”)]
public class User
{}

As far as the ‘Name’ property of the [DataContract] attribute goes, it overrides the name of your datacontract with the name you provide to this property. One use of it, in the context of DataMember attribute is to overload a method within a data contract. A DataContract doesn’t allow two DataMember with the same name, so in such scenario, ‘Name’ property is useful.

0
votes

Based on another question and on:

I am not sure what the Name and Namespace attributes do to the DataContract attribute when calling http://localhost:8081/user/register for example?

I suggest that you are using REST service. When you called the service without setting Namespace to empty string did you define User XML with namespace xmlns="http://tempuri.org"? If not you sent to service different/unknown "data type" and it is probably reason for returned error.