Как заставить службы WCF возвращать сообщения об ошибках с кодом ответа HTTP 200? - PullRequest
4 голосов
/ 17 февраля 2011

Мы пытаемся вернуть наши службы WCF к сообщениям об ошибках с кодом ответа HTTP 200 нашим клиентам Silverlight 4, следуя этой статье на MSDN . Проведя большую часть дня, борясь с конфигурацией, отладкой и поиском соответствующих тем в 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.

Есть ли что-то явно очевидное, что нам не хватает служб, чтобы вернуть код ответа, который мы хотим?

Ответы [ 3 ]

2 голосов
/ 25 февраля 2011

Это оказалось ошибкой в ​​нашем web.config, мы заменили сгенерированную customBinding на basicHttpBinding на наших конечных точках, и теперь все работает как положено.

Странно, но при добавлении «службы WCF с поддержкой Silverlight» вы получаете конфигурацию по умолчанию, которая не работает с Silverlight.

1 голос
/ 17 февраля 2011

Как первоначально предполагалось, использование HTTP-статуса для «сообщения» об ошибках является лучшей практикой.Поэтому, если вы можете сделать это, вам следует.

Что касается вашего решения, я не знаком с описанной моделью, но в базовом WCF вы можете просто попробовать / поймать что угодно, получить исходящий ответ и изменитьоттуда.

Примерно так: (это меняет 400 на 200)

try
{
    throw new WebFaultException(System.Net.HttpStatusCode.BadRequest);
}
catch(WebFaultException)
{
    WebOperationContext.Current.OutgoingResponse.StatusCode = 
                                                  System.Net.HttpStatusCode.OK;
}
1 голос
/ 17 февраля 2011

Или вы можете поместить следующий фрагмент магического кода в конструктор форм Silverlight и оставить службу SOAP-совместимой (возвращая стандарт 500 для ошибок)

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

Я был поражен, когда он работал как шарм.

...