Как писал раньше, используя WCF и Silverlight 3, можно передавать ошибки сервера на клиент. Сейчас расскажу как это можно сделать.
Что же было до появления этой возможности? Если на сервере возникало исключение, оно заворачивалось в SOAP и отправлялось на клиент. Вот только в Silverlight-приложение в том виде как есть оно не попадало. Почему? Да потому, что браузер не пропускал. И вот почему. Браузер имеет стандартный набор ошибок и когда с сервера приходит код ответа не 200, браузер отображать сообщение согласно коду ответа. Когда же на стороне сервера возникает исключение, то по умолчанию код ответа присваивается 500 и в Silverlight-приложении мы видим сообщение "Not found". Хотя, если обращения к серверу мониторить Fiddler'ом, то можно получить общую информацию о серверной ошибке.
Сейчас же есть возможность передать в само Silverlight-приложение полную информацию об ошибке сервера. И так, приступим.
По накатаной схеме создаем Silverlight 3 приложение с Web-приложением для тестирования. В Web-приложение добавляем новый елемент Silverlight-enabled WCF Service . И в решение добавляем еще один проект Class Library. В Class Library создаем класс:
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public override Type BehaviorType
{
get { return typeof(SilverlightFaultBehavior); }
}
protected override object CreateBehavior()
{
return new SilverlightFaultBehavior();
}
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
#region IDispatchMessageInspector Members
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
property.StatusCode = System.Net.HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
#endregion
}
}SilverlightFaultMessageInspector – класс, который в случае ошибки обеспечит код ответа 200, тем самым обеспечит попадание всей информации об ошибке прямо в Silverlight-приложение.
BehaviorExtensionElement – абстрактный класс, который представляет конфигурацию елемента. Специфика данного елемента заключается в том, что он определяет дополнительное поведение сервиса или конечной точки. BehaviorType и CreateBehavior() абстрактные члены этого класса, которые возвращают тип поведения и объект типа поведения соответственно.
Реализуя интерфейс IEndpointBehavior нам важен лишь метод ApplyDispatchBehavior(), что бы добавить нашего “инспектора”. Остальные методы оставим пустыми.
Теперь необходимо в файле конфигурации Web-приложения зарегистрировать наше расширение поведения. Потом, в области конфигурации поведения конечной токи(endpointBehaviors) указать наше зарегистрированое расширение и непосредственно в описании конечной точки указать имя конфигурации поведения(в примере SilverlightFaultBehavior). Также нужно включить передачу ошибок на клиент <serviceDebug includeExceptionDetailInFaults="true"/>. Пример:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="SilverlightFaults"
type="SilverlightFaults.SilverlightFaultBehavior, SilverlightFaults, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="Faults.Web.CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<SilverlightFaults/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="customBinding0">
<binaryMessageEncoding/>
<httpTransport/>
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service behaviorConfiguration="Faults.Web.CalculatorServiceBehavior" name="Faults.Web.CalculatorService">
<endpoint address="" binding="customBinding" bindingConfiguration="customBinding0"
contract="Faults.Web.CalculatorService"
behaviorConfiguration="SilverlightFaultBehavior"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
После описанной конфигурации, все серверные ошибки можно будет получать в Silverlight-приложении с полным описанием. К тому же можно использовать механизм WCF’a c Fault.
Скачть пример.
Больше о передаче ошибок в Silverlight-приложение:
Как видите, если выбирать между WCF-сервисами и Web-сервисами, то предпочтительнее использовать связку Silverlight и WCF