silverlightFaultBehavior для WCF - но все еще получает код 500 - PullRequest
1 голос
/ 05 ноября 2010

Я хочу получить значимое сообщение об ошибке из моей службы WCF для приложения Silverlight 4.После некоторых исследований я обнаружил, что мне нужно изменить код ответа с 500 на 200, если я хочу, чтобы silverlight включил чтение значимого сообщения об ошибке.Вот статья: http://msdn.microsoft.com/de-de/library/ee844556(VS.95).aspx

Я реализовал ее так, как там написано, приложение компилируется, и я могу использовать службу, но я все еще получаю код возврата 500.Основное отличие, которое я вижу, заключается в том, что я вызываю службу через HTTPS , а не через HTTP.Может быть, это причина, почему это не работает?Любая идея, как получить код возврата 200?

Вот мой Web.Config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="ServiceConfiguratorDataSource.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <extensions>
        <behaviorExtensions>
            <add name="silverlightFaults" type="ServiceConfiguratorDataSource.SilverlightFaultBehavior, ServiceConfiguratorDataSource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </behaviorExtensions>
    </extensions>       
    <services>
        <service name="ServiceConfiguratorDataSource.Service" behaviorConfiguration="ServiceConfiguratorDataSourceBehaviour">
            <endpoint address="" binding="customBinding" behaviorConfiguration="SLFaultBehavior" bindingConfiguration="ServiceConfiguratorCustomBinding" contract="ServiceConfiguratorDataSource.IService" />
        </service>
    </services>
    <bindings>
        <customBinding>
            <binding name="ServiceConfiguratorCustomBinding">
                <security authenticationMode="UserNameOverTransport"></security>
                <binaryMessageEncoding></binaryMessageEncoding>
                <httpsTransport/>
            </binding>
        </customBinding>
    </bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceConfiguratorDataSourceBehaviour">
      <serviceMetadata httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="True"/>
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceConfiguratorDataSource.UserCredentialsValidator,ServiceConfiguratorDataSource" />
                </serviceCredentials>
    </behavior>
  </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="SLFaultBehavior">
                <silverlightFaults/>
            </behavior>
        </endpointBehaviors>            
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

... и здесь silverlightFaultBehavior.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;

namespace ServiceConfiguratorDataSource
{
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 System.Type BehaviorType
    {
        get { return typeof(SilverlightFaultBehavior); }
    }

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

}
}

Кто-то знает, если это из-за https ... и если да, то как заставить его работать?

Заранее спасибо,
Фрэнк

ЭДИТ говорит: у меня просто естьдобавлено некоторое ведение журнала: метод ApplyDispatchBehavior вызывается, но метод BeforeSendReply не ... есть идеи, почему?

1 Ответ

1 голос
/ 08 ноября 2010

Если я правильно помню, UserNamePasswordValidator вызывается очень рано в конвейере, еще до того, как диспетчер когда-либо будет вызван, именно поэтому ваше пользовательское поведение отправки ни на что не влияет.(Причина в безопасности: WCF хочет «выбросить» неавторизованные запросы как можно раньше, при этом выполняя для них как можно меньше кода).Как вы сами предложили в комментариях, одним из решений было бы просто проверить учетные данные позже в конвейере - например, в каждой операции (или, может быть, даже в AfterReceiveRequest инспектора сообщений?)

...