2

I am using a DI pattern with a set of WCF services, and Unity is acting as my IoC container. I have completed unit and functional testing from the service down and everything is working as I would expect. I am now testing the endpoints themselves and I have run into an issue with serializing my results.

My service looks something like this:

public class ProcessingService : IProcessingService
{
    private IOrderService orderService;
    public ProcessingService(IOrderService orderService)
    {
        this.orderService = orderService;
    }

    [WebInvoke(Method = "Get", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    public IOrder CreateNewOrder(string venNum, OrderType orderType, string orderDescription, string createdBy)
    {
        return orderService.CreateNewOrder(venNum, orderType, orderDescription, createdBy);
    }
}

orderService.CreateNewOrder ultimately returns a complex object that looks similar to this

internal partial class Order : IOrder
{
    [DataMember]
    public int VenNum { get; set; }
    [DataMember]
    public string Description { get; set; }
    [DataMember]
    public IList<string> RuntimeErrorMessages { get; set; }
    [DataMember]
    public IList<IOrderDetail> OrderDetails { get; set; }
}

This generates the exception:

"<type> is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

This error makes sense since you can't possibly serialize or deserialize an interface. Further I can get this error to go away by changing the return type of my service method to

public Order CreateNewOrder(...)

I don't want to expose my concrete objects though, so I am at a bit of an impasse here. In the past I can recall using Json.Net's JsonConverter class to serialize and deserialize objects like this although I wasn't using DI at that time and it was a little bit easier. So how do I go about serializing my complex types without exposing my concrete types? The exception mentions using a DataContractSerializer but it appears that I would have to write one Serializer for every complex type I want to return and that isn't practical.

Suggestions are greatly appreciated!

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
dparsons
  • 2,812
  • 5
  • 28
  • 44
  • 1
    Why don't you want to expose your concrete objects? – Mark Seemann Oct 28 '15 at 15:53
  • I don't think this is related to dependency injection. Also, what Mark says. A contract is based upon a concrete type. – CodeCaster Oct 28 '15 at 16:00
  • @MarkSeemann It tightly couples my endpoint to the concrete type which is what I am trying to avoid. – dparsons Oct 28 '15 at 16:12
  • @CodeCaster I would argue the other way that a concrete type can be based on an interface. This is only related to DI in the sense that it is the pattern that I am using. – dparsons Oct 28 '15 at 16:16
  • Dependency injection is not related to your problem. There could as well be `orderService = new OrderService` in your ctor and you'd still see the same results. WCF prevents you to shoot yourself in the foot by default, so it does not allow interfaces as contracts. It cannot (de)serialize into an interface. It can, but then you'd have to do it yourself. – CodeCaster Oct 28 '15 at 16:18
  • 3
    Your endpoint isn't object-oriented http://blog.ploeh.dk/2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented There's no coupling via .NET types, only WSDL. – Mark Seemann Oct 28 '15 at 16:18
  • @MarkSeemann I read your article and it made a lot of sense. If you turn your comment into an answer I will go ahead an accept it. Thanks a lot! – dparsons Nov 18 '15 at 01:18

2 Answers2

4

The desire to decrease coupling is laudable, but at the boundary, an application is no longer object-oriented. Particularly for WCF applications, the boundary is defined by XSD and WSDL, so the data travelling over the wire is no longer objects, but rather XML (or, at least, XML infosets). That data has no behaviour.

The coupling between a SOAP service and its clients is defined by the contract; i.e. the WSDL. Even if you could return interfaces in your implementation, it would still travel over the wire as XML, so it would make no difference.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
0

As stated above this has nothing to do with anything else than serialization, and I'd like to quote another answer:

No. You can't serialize an interface. Ever.

You have to serialize a concrete class, and the contract has to be a concrete class. A DTO object if you will. Also this blog post might be interesting, it goes through some of the conceptual differences and difficulties with DTOs and POCOs.

Community
  • 1
  • 1
flindeberg
  • 4,887
  • 1
  • 24
  • 37
  • As I said in my original post "This error makes sense since you can't possibly serialize or deserialize an interface. " That fact isn't lost on me. What I am trying to get to is if there is some generic way to keep me from coupling my service class to the library that contains my POCOs. That is why I flagged this as DI in the hopes that I could leverage my container for this. I can, for example, change my return type to string and then return a serialized representation of what comes back from orderService.CreateNewOrder(...) but I am on the fence about that. – dparsons Oct 29 '15 at 11:29