user1552485
user1552485

Reputation: 53

WCF - Cannot create abstract class

I'm writing a WCF webservice and passing in a complex type as a parameter of the method. The complex type looks like this:

 [DataContract(Namespace = "")]
public class MyRequest 
{
    [DataMember()]
    public string TransactionId { get; set; }

    [DataMember(IsRequired = true)]
    public bool IsRollback { get; set; }

    [DataMember(IsRequired = true)]
    public OrderType OrderType { get; set; }

    [DataMember(IsRequired = true)]
    public ICustomerId CustomerId { get; set; }

    [DataMember()]
    public long OrderId { get; set; }

    [DataMember()]
    public AnotherComplexType PurchaseInfo { get; set; }

The webservice method looks like this:

[ServiceKnownType(typeof(CustomerIdByName))]
[ServiceKnownType(typeof(CustomerIdByAccount))]
public OrderResult Execute(MyRequest order) {
}

The Interface looks like this:

[KnownType(typeof(CustomerIdByAccount))]    
[KnownType(typeof(CustomerIdByName))]
public interface ICustomerId{

string GetId();
}

When I make a request using the SOAP end point, everything works just great. But when passing the request to the REST end point, I get the serialization error.

This is the request I'm using

<MyRequest>
<CustomerId>
<AccountId>59251</AccountId>
</CustomerId>
<IsRollback>false</IsRollback>
<OrderId>0</OrderId>
<OrderType>OrderSubscription</OrderType>
<PurchaseInfo>
<ObjectId>196521</ObjectId>
</PurchaseInfo>
<TransactionId>ABC123</TransactionGuid>
</MyRequest>

Since I had been stuck at this point for too long, I then changed the ICustomerId member to be an abstract class that implements ICustomerId. Again the SOAP end point works fine but sending the request to the rest end point I get an error that states "Cannot create abstract class"

What am I missing or doing wrong here?

Is this failing because the interface is nested in the complex type and not a direct parameter of the webservice method? I've used webservices that receive interfaces as parameter and with the KnownType decorators they work just fine. Same question applies to the abstract class, is this not working because the abstract class is nested within a member of the MyRequest complex type?

This is the error message I am getting:

Element CustomerId from namespace cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML

Upvotes: 3

Views: 4231

Answers (1)

Sinaesthetic
Sinaesthetic

Reputation: 12211

Have you tried decorating your interface as a RESTful method?

[ServiceContract]
public interface IMyRequest
{
    [OperationContract]
    [WebInvoke(
       UriTemplate = "Requests/GetID",
       Method = "POST",
       BodyStyle = WebMessageBodyStyle.Wrapped)]
    string GetId(MyRequest myRequest);
...

Also:

  • make sure that the [DataMember] properties match your request payload. Everything that gets passed in your XML request payload must be caught by the serializer in the service. I recommend keeping the naming the same, but you can map it using [DataMember(name="MyProperty")]. Also, your [DataContract] must be mapped to match the name of the parent node of your XML payload like [DataContract(Name="MyRequest")] but only if the class is named differently than the xml node. Do this, and it will deserialize your xml into the server side object/dto
  • The error you're getting sounds like it's complaining about the complex type inside of your DataContract. Your complex type needs to be decorated for serialization the same as your MyRequest type.
  • Also ensure your REST endpoint is bound to webHttpBinding

Upvotes: 0

Related Questions