如何让WCF服务返回带有HTTP 200响应代码的错误消息?

时间:2011-02-17 12:12:09

标签: wcf silverlight-4.0 c#-4.0

我们正试图让我们的WCF服务在this article on MSDN之后使用HTTP 200响应代码返回到我们的Silverlight 4客户端的故障消息。经过一天的大部分时间都在配置,调试和搜索SO上的相关主题,我们仍然没有工作。

这是我们的SilverlightFaultBehaviour类:

public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
        EndpointDispatcher endpointDispatcher)
    {
        SilverlightFaultMessageInspector inspector = 
        new SilverlightFaultMessageInspector();
        endpointDispatcher.DispatchRuntime
            .MessageInspectors.Add(inspector);
    }

    public class SilverlightFaultMessageInspector : IDispatchMessageInspector
    {
        public void BeforeSendReply(ref Message reply,
            object correlationState)
        {
            if (reply.IsFault)
            {
                HttpResponseMessageProperty property = 
                    new HttpResponseMessageProperty();

                // Here the response code is changed to 200.
                property.StatusCode = System.Net.HttpStatusCode.OK;

                reply.Properties[HttpResponseMessageProperty.Name] = property;
            }
        }

        public object AfterReceiveRequest(ref Message request,
            IClientChannel channel, 
            InstanceContext instanceContext)
        {
            // Do nothing to the incoming message.
            return null;
        }
    }

    // The following methods are stubs and not relevant. 
    public void AddBindingParameters(ServiceEndpoint endpoint,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, 
        ClientRuntime clientRuntime)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public override Type BehaviorType
    {
        get { return typeof(SilverlightFaultBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new SilverlightFaultBehavior();
    }
}

这是我们web.config的相关片段:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="FooWebServiceBehaviour">
        <serviceDebug includeExceptionDetailInFaults="true" />
        <serviceMetadata httpGetEnabled="true" />
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior name="SilverlightFaultBehavior">
        <silverlightFaults />
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <services>
    <service name="Foo.Web.Services.BarService" behaviorConfiguration="FooWebServiceBehaviour">
      <endpoint address="" binding="customBinding"
        bindingConfiguration="Foo.Web.Services.HttpBinding"
        contract="Foo.Web.Service.IBarService"
        behaviorConfiguration="SilverlightFaultBehavior" />
    </service>
  </services>
  <extensions>
    <behaviorExtensions>
      <add name="silverlightFaults"
        type="Foo.Web.Behavior.SilverlightFaultBehavior, Foo.WebBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
</system.serviceModel>

问题似乎是从不调用BeforeSendReply方法,并且每次抛出FaultException时我们的客户端仍然会收到有用的“Not Found”错误。

是否有一些显而易见的事情表明我们缺少让服务返回我们想要的响应代码?

3 个答案:

答案 0 :(得分:2)

在我们的web.config中发现这是一个错误,我们在端点上用basicHttpBinding替换了生成的customBinding,现在事情按预期工作了。

奇怪的是,当添加“启用Silverlight的WCF服务”时,会为您提供一个似乎不适用于Silverlight的默认配置。

答案 1 :(得分:1)

或者您可以将以下魔术代码段放入Silverlight表单构造函数中,并保持服务SOAP兼容(返回stadard 500以查找错误)

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

当它像魅力一样时,我感到很惊讶。

答案 2 :(得分:1)

如最初建议的那样,使用HTTP状态来“沟通”故障是最佳做法。所以,如果你能做到这一点,你应该这样做。

至于你的解决方案,我不熟悉所描述的模型,但在基础WCF中你可以尝试/捕获任何内容,获取传出响应,并从那里进行修改。

像这样:(这会改变400到200)

try
{
    throw new WebFaultException(System.Net.HttpStatusCode.BadRequest);
}
catch(WebFaultException)
{
    WebOperationContext.Current.OutgoingResponse.StatusCode = 
                                                  System.Net.HttpStatusCode.OK;
}