English 中文(简体)
WCF Problem Sending Object To Client
原标题:

Background

Converting from using .Net Remoting to WCF. Most of the methods on the WCF server are working fine, but ran into one that isn t working today.

This is the service contract:

[ServiceContract]
public interface IMyService
{
  [OperationContract]
  generated.Response.ACS_Response Check(generated.Request.ACS_Request request);
}

I snipped out the rest of the methods on that interface, since they are working. Basically, I m trying to pass in a request object and get back a response object.

The classes for ACS_Response and ACS_Reqeust are generated using XSD.exe against an XSD file. Those classes reside in an Api assembly that is referenced by both the WCF client and WCF host.

Problem

I am able to make the call to the WCF host and the Request object and the host is able to do its work. When the host attempts to return the Response object, that s where I encounter an exception.

I turned on tracing for WCF and see an SerializationException saying:

Type  Api.generated.Response.ACS_ResponseQuestion 
with data contract name  ACS_ResponseQuestion:http://...  is
not expected.  Add any types not known statically.........

Questions

First, I m confused because I am able to successfully send a Request object, so it would seem the basics are working.

Second, this serialization was working under .Net Remoting. The classes are all generated by WSDL so shouldn t they be serializable as is?

Third, the host and client both reference the same Api assembly which defines these classes, so they are known to both server and client.

最佳回答

I believe it is because Api.generated.Response.ACS_ResponseQuestion is not used in the contract (API) so it is not automatically tagged as a known type.

Read these articles, they should explain everything:

  1. Known Types
  2. Data Contract Known Types
  3. Understanding Known Types

Quick solution: Try adding this to the class which implements the interface:

[KnownType(typeof(Api.generated.Response.ACS_ResponseQuestion))]

If this doesn t work, you may have to declare it as a ServiceKnownType:

// Define a service contract and apply the ServiceKnownTypeAttribute
// to specify types to include when generating client code. 
// The types must have the DataContractAttribute and DataMemberAttribute
// applied to be serialized and deserialized. The attribute specifies the 
// name of a method (GetKnownTypes) in a class (Helper) defined below.
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
[ServiceContract()]
public interface ICatalog
{
    // Any object type can be inserted into a Hashtable. The 
    // ServiceKnownTypeAttribute allows you to include those types
    // with the client code.
    [OperationContract]
    Hashtable GetItems();
}

// This class has the method named GetKnownTypes that returns a generic IEnumerable.
static class Helper
{
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
    {
        System.Collections.Generic.List<System.Type> knownTypes =
            new System.Collections.Generic.List<System.Type>();
        // Add any types to include here.
        knownTypes.Add(typeof(Widget));
        knownTypes.Add(typeof(Machine));
        return knownTypes;
    }
}

[DataContract()]
public class Widget
{
    [DataMember]
    public string Id;
    [DataMember]
    public string Catalog;
}

[DataContract()]
public class Machine : Widget
{
    [DataMember]
    public string Maker;
}
问题回答

Take a look at this ServiceKnownType provider It should save you some grief. Its very simple for you to register a base type and it will scan the assembly for all classes that inherit from the base class.

You are referencing the classes from both the client and the server, I would therefore recommend that you look at this way of doing WCF:

http://www.dnrtv.com/default.aspx?showNum=122





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签