我需要创建一个应该从javascript调用的wcf服务。该服务定义如下:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class ClientRequestService : IClientRequestService
{
[WebGet]
[ApplyProxyDataContractResolver]
public ResponseData ProcessClientRequest(String pageId)
{
...
}
}
此方法应返回在编译时我不知道的类型的对象。因此,当它被调用时,我得到以下异常:
不希望使用数据合同名称...键入...考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 - 例如,使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。
我创建自定义DataContractResolver并创建一个实现接口IOperationBehavior的属性,以便将我的自定义DataContractResolver附加到我的服务。
public class ApplyProxyDataContractResolverAttribute : Attribute, IOperationBehavior
{
public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
{
var dataContractSerializerOperationBehavior =
description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
}
}
方法ApplyDispatchBehavior被成功调用,但我的自定义DataContractResolver的方法永远不会被调用,我得到相同的异常。
我尝试使用ServiceRoute类或使用svc文件注册我的服务 - 它无论如何都不起作用。
答案 0 :(得分:2)
我认为,问题在于WebHttpBehavior和WebScriptEnablingBehavior已经插入了自己的序列化格式化程序,它插入了自己的序列化操作行为,插入了自己的序列化程序。您的路径永远不会被调用,因为在所有序列化和反序列化上都会调用自定义序列化程序。
您需要做的是完全覆盖该路径。这是你如何做到的。
如果您现在正在使用WebHttpBehavior,请将其子类化。如果您正在使用WebScriptEnablingBehavior,请改为使用它。
然后覆盖这两个方法:
System.ServiceModel.Description.WebHttpBehavior.GetDefaultClientFormatter(OperationDescription, Boolean, Boolean) : IClientMessageFormatter
和
System.ServiceModel.Description.WebHttpBehavior.GetDefaultDispatchFormatter(OperationDescription, Boolean, Boolean) : IDispatchMessageFormatter
要了解如何覆盖它们,请使用Reflector并查看它们在WebHttpBehavior和WebScriptEnablingBehavior中的默认实现。
你会注意到你必须插入自己的操作格式化程序,然后插入自己的操作行为,然后插入新的序列化程序。看一下DataContractJsonSerializerOperationFormatter和DataContractJsonSerializerOperationBehavior的实现,看看它们是如何被使用和实例化的,看看我的意思。
我知道这比你想要的更多,但它比听起来更简单,它会让你完全按照自己的意愿行事!