views:

2101

answers:

3

Hi guys

I have the following:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

When I run the Get method I get the following error:

There was an error while trying to serialize parameter http://tempuri.org/%3AGetResult. The InnerException message was 'Type 'PPS.Core.DomainModel.Support.Action.ActionResult`1[ [PPS.Core.DomainModel.SportProgram.ISportProgram, PPS.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action' is not expected. 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.'. Please see InnerException for more details.

From this error I can see that it can resolve ActionResult but it can't resolve ISportProgram even though I have ServiceKnownType(typeof(ActionResult < SportProgram >)) on my service interface...

Note this is the Reference stub that is generated looks like this, so I can see that the known types are being brought across correctly:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

Why is this going wrong???? Note its getting through the WCF service correctly... but it throws the exception when the result is returned.

Lastly ActionResult looks like this:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

Cheers Anthony

A: 

Are you specifying interfaces in the objects and not concrete types?

PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>

Edit:

What I'm saying is that are all the concrete types that you are passing in the generics (including in sub object via interfaces) being passed in the Known Types list. We've had serialasation issues where all the types were not known.

Preet Sangha
what do you mean by that? The concreat object implements the interface...
vdhant
A: 

You are returning a IList of T. It maybe that the system has problems finding out what T is.

Not sure if it is ok to return an interface rather than a type.

Shiraz Bhaiji
+7  A: 

Well, I think this is another case of the SOA vs. OOP "impedance mismatch". The two world are quite separate.

In WCF, all that is being passed from the client to the server is passed as serialized messages - no references are being used.

This means: everything you want to serialize on the client, send it across to the server, and deserialize it and use it there, must be concrete - you cannot pass around interfaces, you cannot use "non-resolved" generics - you need to spell it out. Basically, all that's being passed from client over the wire to the server must be expressable in XML schema.

This has lots of implications:

  • no interfaces - you cannot pass around interfaces - you need to work with concrete types
  • no "automatic" inheritance - you cannot just define a base class and pass around derived classes based on it - those need to be specificied too (that's what the ServiceKnownType attribute is for)
  • no automatic generics - again, you need to use concrete types instead

This may sound like a lot of restrictions - but it's because WCF is using all message-based communication - it cannot deal with refereces, inheritance, generics etc. - you need to spell it out.

So I don't really have an answer for you per se - I just think you need to rethink your strategy and change the way your client and server are exchanging information over WCF.

Marc

PS: I did some more research, and contrary to all my understanding, there seems to be a way to serialize anything that's based on an interface and/or abstract base class across the wire, as long as you can be sure it's always only .NET on either end of the wire (i.e. it's not interoperable with e.g. Java).

See Aaron Skonnard blog post on the NetDataContractSerializer and another blog post and yet another showing how to use the NetDataContractSerializer to be able to pass around things like IPerson as parameters to your methods.

marc_s
I'm willing to give WCF all the hints it needs but I can not avoid using the interfaces or the generics... if somehow I can get rid of the interfaces can I still use generics?? also is the reverse true if i can get rid of the generics can I still use interfaces... meaning is it just the combinaton of the 2 that are causing me issues?? Because I could create more specific version of IActionResult<ISportProgram> that doesn't require the generics to be used...
vdh_ant
Updated my post with some new info I found while researching this matter - hope this helps!
marc_s
Thanks for the update... in my case NetDataContractSerializer works great...
vdh_ant