【问题标题】:How to get WCF services to return fault messages with an HTTP 200 response code?如何让 WCF 服务返回带有 HTTP 200 响应代码的错误消息?
【发布时间】:2011-02-17 12:12:09
【问题描述】:

我们正试图让我们的 WCF 服务返回故障消息,并在 this article on MSDN 之后向我们的 Silverlight 4 客户端发送 HTTP 200 响应代码。花了一天的大部分时间在 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 的相关 sn-p:

<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 时,我们的客户仍然会收到有用的“未找到”错误。

我们是否缺少明显的东西来让服务返回我们想要的响应代码?

【问题讨论】:

    标签: wcf silverlight-4.0 c#-4.0


    【解决方案1】:

    这原来是我们的 web.config 中的一个错误,我们在端点上用 basicHttpBinding 替换了生成的 customBinding,现在一切正常。

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

    【讨论】:

      【解决方案2】:

      或者您可以将以下魔术代码 sn-p 放入您的 Silverlight 表单构造函数并保持服务 SOAP 兼容(返回标准 500 错误)

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

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

      【讨论】:

      • 我们尝试更改客户端 HTTP 堆栈,它确实很有魅力。但是,我们用于发布/订阅消息交换的Laharsub 似乎破坏了客户端功能。一段时间后,客户端停止接收消息。这似乎是那些修复一件事会破坏另一件事的日子之一。
      【解决方案3】:

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

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

      类似这样的:(这会将 400 更改为 200)

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-11
        • 1970-01-01
        • 2018-02-13
        • 1970-01-01
        • 2014-03-14
        • 1970-01-01
        • 2016-12-23
        • 2012-07-02
        相关资源
        最近更新 更多