2010-11-05 72 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

相關問題