2010-11-05 74 views
1

我想从我的WCF服务中获得有意义的错误消息对我的Silverlight 4应用程序。经过一番调查后,我发现如果我希望Silverlight能够读取有意义的错误消息,我需要将答复代码从500更改为200。这里是文章:http://msdn.microsoft.com/de-de/library/ee844556(VS.95).aspxsilverlightFaultBehavior为WCF - 但仍然获得码500

我已经实现它,因为它写在那里,应用程序编译,我可以使用服务 - 但我仍然得到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 ...和,如何让它起作用?

由于提前,
弗兰克

EDITH说:我只是添加了一些记录:在ApplyDispatchBehavior - 方法被调用,但BeforeSendReply - 方法不...任何想法,为什么?

+0

是什么原因造成的故障在第一时间,当你看到500响应代码? (它是一个[OperationContract的]方法中抛出的异常?FaultException异常的显式抛出?别的东西吗?你可以尝试明确地抛出一个FaultException异常,看看这仍然发生?) – 2010-11-05 23:28:37

+0

这是一个明确的FaultException我在UserNamePasswordValidator派生类扔。我故意发送错误的用户凭据,所以验证器会抛出异常。如果这就是我仍然得到500的原因...更多理由踢这个破解UserNameOverTransport身份验证,并简单地检查我的服务的每个方法调用凭据。 – Aaginor 2010-11-08 10:54:15

回答

1

如果我没有记错,在UserNamePasswordValidator被调用的管道很早,调度员曾经被调用,这就是为什么您的自定义调度行为没有影响任何东西之前。 (原因是安全性:WCF希望尽可能早地“抛出”未授权的请求,同时尽可能少地为它们运行代码)。 正如你自己在评论中所建议的,一种解决方案是稍后在管道中验证凭证 - 例如,在每一个操作(或者甚至在消息检查的AfterReceiveRequest?)

+0

我想我会验证每个操作中的凭证。无论如何,我需要访问有关用户的信息,因为结果可能取决于当前用户授予的权限。非常感谢 :) – Aaginor 2010-11-08 17:41:19

相关问题