views:

1833

answers:

4

Hey everyone,

I've just started playing with the REST starter kit, and I've hit a road block trying to build my own service. I'm trying to create a service for account management, and I can't get the service to serialize my objects, throwing the following error:

Unable to deserialize XML body with root name 'CreateAccount' 
and root namespace '' (for operation 'CreateAccount' and 
contract ('Service', 'http://tempuri.org/')) using 
DataContractSerializer. Ensure that the type corresponding to 
the XML is added to the known types collection of the service.

Here's the actual code for the service (based off of the 'DoWork' method that came with the project):

[WebHelp(Comment = "Creates a Membership account")]
[WebInvoke(UriTemplate = "CreateAccount", RequestFormat = WebMessageFormat.Xml)]
[OperationContract]
public ServiceResponse CreateAccount(CreateAccount request)
{
    try
    {
        // do stuff

        return new ServiceResponse()
        {
            Status = "SUCCESS",
            ErrorMessage = ""
        };
    }
    catch (Exception ex)
    {
        return new ServiceResponse()
        {
             Status = "ERROR",
             ErrorMessage = ex.Message + "\n\n" + ex.StackTrace
        };
    }
}

And last, but not least, here's the object that's causing all the trouble:

public class CreateAccount { public string FirstName { get; set; }

public string LastName { get; set; }

public string Email { get; set; }

public bool SignUpForNewsletter { get; set; }

public string Password { get; set; }

}

Am I missing anything stupid?

Thanks in advance!

+1  A: 

If you don't have it already, I think a [DataContract] attribute above your CreatAccount class.

PaulWarren
+3  A: 

It appears the problem is a namespace clash between your method name "CreateAccount" and your input type "CreateAccount".

Also, you have to mark your CreateAccount type as a DataContract like so:

[DataContract]
public CreateAccount
{
    [DataMember]
    public string LastName { get; set; }

    ...
}

If you want to keep the same name, you can specify a namespace for the CreateAccount class.

I noticed you have a return type as well. Ensure the return type is marked with the DataContract attribute as well. Also, specify the return format like so:

ResponseFormat = WebMessageFormat.Xml
Doanair
I just thought about a possible naming conflict with object and the method. I've changed to object name to 'CreateAccountRequest', as well as, added the [DataContract] and [DataMember] attributes, but no luck.
Joel.Cogley
See above edit. Ensure you are specifying the attributes on your service contract as well. You should have a service interface. That is where the OperationContract and WebInvoke attributes should live.
Doanair
+1  A: 

It turns out, all I was missing an extra value on the [DataContract] attribute on the business object.

The final attribute was '[DataContract(Namespace = "")]'

Thanks everyone for your help!

--J

Joel.Cogley
A: 

I had a similar problem, but I did have the DataContract attribute. What I was missing though was the xmlns="http://uri.org" attribute from the root element when trying to read the xml back into the object.
e.g.

<Root_Element xmlns="http://uri.org"&gt;&lt;Child_Element/&gt;...&lt;/Root_Element&gt;
Anthony K