Windows服务托管基于SSL的WCF对象(https) - 自定义JSON错误处理不起作用

时间:2010-06-09 19:51:07

标签: ajax wcf ssl https

我将首先展示在非ssl(http)环境中工作的代码。此代码使用自定义json错误处理程序,并抛出所有错误,确实冒泡到客户端javascript(ajax)。

        // Create webservice endpoint
        WebHttpBinding binding = new WebHttpBinding();

        ServiceEndpoint serviceEndPoint = new ServiceEndpoint(ContractDescription.GetContract(Type.GetType(svcHost.serviceContract + ", " + svcHost.assemblyName)), binding, new EndpointAddress(svcHost.hostUrl));

        // Add exception handler
        serviceEndPoint.Behaviors.Add(new FaultingWebHttpBehavior());

        // Create host and add webservice endpoint
        WebServiceHost webServiceHost = new WebServiceHost(svcHost.obj, new Uri(svcHost.hostUrl));
        webServiceHost.Description.Endpoints.Add(serviceEndPoint);

        webServiceHost.Open();

我还将向您展示FaultingWebHttpBehavior类的外观:

public class FaultingWebHttpBehavior : WebHttpBehavior
{
    public FaultingWebHttpBehavior()
    {         
    }

    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ErrorHandler());
    }

    public class ErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return true;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // Build an object to return a json serialized exception
            GeneralFault generalFault = new GeneralFault();
            generalFault.BaseType = "Exception";
            generalFault.Type = error.GetType().ToString();
            generalFault.Message = error.Message;                

            // Create the fault object to return to the client
            fault = Message.CreateMessage(version, "", generalFault, new DataContractJsonSerializer(typeof(GeneralFault)));
            WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

        }
    }
}

[DataContract]
public class GeneralFault
{
    [DataMember]
    public string BaseType;

    [DataMember]
    public string Type;

    [DataMember]
    public string Message;
}

一旦调用了webServiceHost.Open(),就会自动调用AddServerErrorHandlers()方法。这设置了自定义json错误处理程序,生活很好: - )

当我们切换到SSL(https)环境时,问题就出现了。我现在将向您展示SSL的端点创建代码:

        // Create webservice endpoint
        WebHttpBinding binding = new WebHttpBinding();
        ServiceEndpoint serviceEndPoint = new ServiceEndpoint(ContractDescription.GetContract(Type.GetType(svcHost.serviceContract + ", " + svcHost.assemblyName)), binding, new EndpointAddress(svcHost.hostUrl));

        // This exception handler code below (FaultingWebHttpBehavior) doesn't work with SSL communication for some reason, need to resarch...
        // Add exception handler
        serviceEndPoint.Behaviors.Add(new FaultingWebHttpBehavior());

        //Add Https Endpoint
        WebServiceHost webServiceHost = new WebServiceHost(svcHost.obj, new Uri(svcHost.hostUrl));
        binding.Security.Mode = WebHttpSecurityMode.Transport;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
        webServiceHost.AddServiceEndpoint(svcHost.serviceContract, binding, string.Empty);

现在,使用此SSL端点代码,服务可以正常启动,并且可以通过客户端javascript轻松地与wcf托管对象进行通信。但是,自定义错误处理程序不起作用。原因是,在运行webServiceHost.Open()时,不会调用AddServerErrorHandlers()方法。

那么,谁能告诉我这张照片有什么问题?为什么AddServerErrorHandlers()没有被自动调用,就像我使用非ssl端点时一样?

谢谢!

1 个答案:

答案 0 :(得分:0)

我将推荐您使用MSDN文档

  

如果指定了传输值   该   的WebHttpBinding(WebHttpSecurityMode)   那么提供的设置   运输财产变得有效   用于服务端点。的价值   WebHttpSecurityMode只能在中设置   WebHttpBinding构造函数   将其作为一个明确的参数和   它的值不能再设置   绑定实例已创建。

请参阅:http://msdn.microsoft.com/en-us/library/bb348328.aspx

所以你需要传递这个值

binding.Security.Mode = WebHttpSecurityMode.Transport;

进入你的.ctor()

WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);

我之前从未使用过这个,因为我总是将我的绑定声明为web.config文件,但根据MSDN,这是你应该做的。