我正在尝试使用渠道工厂从此link调用来自Silverlight客户端的WCF服务。与渠道工厂合作对我来说是新鲜事,所以请耐心等待我!
文章中提到的一切都很好。但是现在我正在尝试实现Fault异常,以便我可以捕获Silverlight端的实际异常。但由于某种原因,我总是最终捕捉到不符合我目的的CommunicationException。
这是我的服务合同:
[OperationContract]
[FaultContract(typeof(Fault))]
IList<Category> GetCategories();
抓住服务块:
catch (Exception ex)
{
Fault fault = new Fault(ex.Message);
throw new FaultException<Fault>(fault, "Error occured in the GetCategories service");
}
具有异步模式的客户的服务合同:
[OperationContract(AsyncPattern = true)]
[FaultContract(typeof(Fault))]
IAsyncResult BeginGetCategories(AsyncCallback callback, object state);
IList<Category> EndGetCategories(IAsyncResult result);
以下是来自客户的服务电话:
ICommonServices channel = ChannelProviderFactory.CreateFactory<ICommonServices>(COMMONSERVICE_URL, false);
var result = channel.BeginGetCategories(
(asyncResult) =>
{
try
{
var returnval = channel.EndGetCategories(asyncResult);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
CategoryCollection = new ObservableCollection<Category>(returnval);
});
}
catch (FaultException<Fault> serviceFault)
{
MessageBox.Show(serviceFault.Message);
}
catch (CommunicationException cex)
{
MessageBox.Show("Unknown Communications exception occured.");
}
}, null
);
我在服务和客户端应用程序之间共享DataContract .dll,因此它们指的是相同的数据协定类(类别和故障)
请告诉我我做错了什么?
更新:我确实清楚地看到了Fiddler中服务发送的故障异常。这让我相信我在客户端缺少一些东西。
答案 0 :(得分:1)
要在sivleright中捕获常规异常,您必须创建“启用Silverlight的WCF服务”(添加 - >新项 - &gt;启用Silverlight的WCF服务)。 如果您已经创建了标准WCF服务,则可以手动将属性[SilverlightFaultBehavior]添加到服务中。 此属性的默认实现是:
public class SilverlightFaultBehavior : Attribute, IServiceBehavior
{
private class SilverlightFaultEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new SilverlightFaultMessageInspector());
}
public void Validate(ServiceEndpoint endpoint)
{
}
private class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if ((reply != null) && reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
property.StatusCode = HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
endpoint.Behaviors.Add(new SilverlightFaultEndpointBehavior());
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
答案 1 :(得分:0)
我们在服务器上使用自己的自定义ServiceException类,例如
[Serializable]
public class ServiceException : Exception
{
public ServiceException()
{
}
public ServiceException(string message, Exception innerException)
: base(message, innerException)
{
}
public ServiceException(Exception innerException)
: base("Service Exception Occurred", innerException)
{
}
public ServiceException(string message)
: base(message)
{
}
}
然后在我们的服务器端服务方法中,我们使用这样的错误处理:
try
{
......
}
catch (Exception ex)
{
Logger.GetLog(Logger.ServiceLog).Error("MyErrorMessage", ex);
throw new ServiceException("MyErrorMessage", ex);
}
然后我们对所有Web服务调用使用通用方法:
/// <summary>
/// Runs the given functon in a try catch block to wrap service exception.
/// Returns the result of the function.
/// </summary>
/// <param name="action">function to run</param>
/// <typeparam name="T">Return type of the function.</typeparam>
/// <returns>The result of the function</returns>
protected T Run<T>(Func<T> action)
{
try
{
return action();
}
catch (ServiceException ex)
{
ServiceLogger.Error(ex);
throw new FaultException(ex.Message, new FaultCode("ServiceError"));
}
catch (Exception ex)
{
ServiceLogger.Error(ex);
throw new FaultException(GenericErrorMessage, new FaultCode("ServiceError"));
}
}