Jeff
Jeff

Reputation: 14279

Null values for object properties de-serialized by WCF

I have a WCF web service that used to work fine. Somewhere down the line it stopped and I cant tell why. The code and the interface never changed nor did the web.config (at least not in relation to the web services section). I have a class:

[DataContract]
public class QuizServiceArgs
{
    [DataMember(IsRequired = true, Order = 1)] 
    public int Category1 { get; set; }

    [DataMember(IsRequired = true, Order = 2)] 
    public int Category2 { get; set; }

    [DataMember(IsRequired = true, Order = 3)] 
    public int Category3 { get; set; }

    [DataMember(IsRequired = true, Order = 4)] 
    public int Category4 { get; set; }
}

And the service interface is simple:

public interface IQuizService
{
    [OperationContract]
    [WebInvoke(Method = "POST",
       BodyStyle = WebMessageBodyStyle.WrappedRequest,
       ResponseFormat = WebMessageFormat.Json)]
    ServiceResult Save(QuizServiceArgs answers, string strvalue, int intvalue);
}

The second two params strvalue and intvalue were added only for troubleshooting to see if those were getting deserialized -- and they are. When I hit the service, I get an error saying that I'm missing the Category1 parameter from the request but as you can see this Fiddler screenshot, the values are there.

fiddler screenshot

I can get primitive values to pass in but objects seem to all be instantiated with null or default values. What am I doing wrong?

UPDATE

I never actually got my original question answered which sucks, but Sixto suggested that I switch my serialization to JSON. JSON was the original design but got nixed when I was having trouble with it. After I successfully switched back to JSON, everything was serializing and deserializing properly. Now I am just waiting for this to break for no explanation so I can switch back to XML....

Upvotes: 7

Views: 13406

Answers (2)

M.R.
M.R.

Reputation: 4837

You have a namespace issue. By default, when you create an interface for the servicecontract, it assigns it a namespace. Namespace is like scope for the SOAP xml elements, and if it doesn't fall under the same scope, it thinks it doesn't exist. Chances are the code that posts stoppped providing the namespace(?). You have to refer by it when posting the XML - but I'm not entirely sure what it assigns(something server specific), so it is good practice to always define a namespace, like so:


[ServiceContract(Namespace = "your namespace")]
public interface IQuizService 
{     
     [OperationContract]     
     [WebInvoke(Method = "POST",        
            BodyStyle = WebMessageBodyStyle.WrappedRequest,        
            ResponseFormat = WebMessageFormat.Json)]     
            ServiceResult Save(QuizServiceArgs answers, string strvalue, 
                int intvalue); 
} 

And then the posts should have the namespace in the SOAP request.


<Save xmlns="your namespace">.....</Save>

The namespace should also match your service declaration in web.config.

Also need it in the datacontract

[DataContract(Namespace = "your namespace")]

Upvotes: 8

Sixto Saez
Sixto Saez

Reputation: 12680

The DataMember IsRequired attribute tells the WCF deserializer to expected an element in the message XML with that name (at least it does for soap deserialization). It sounds like the client code that is generating the message request is no longer sending all the Category... elements. It doesn't mean you can't send a null value for a DataMember marked IsRequired, it just means the element needs to exist in the message.

UPDATE: looking at the XML more closely, shouldn't there be a QuizServiceArgs element in the XML?

Upvotes: 5

Related Questions