Поймать исключение ошибки в Silverlight с фабрикой каналов - PullRequest
0 голосов
/ 03 октября 2011

Я пытаюсь вызвать службу WCF из клиента Silverlight, используя фабрику каналов, согласно этой ссылке . Работа с фабрикой каналов - это что-то новое для меня, поэтому, пожалуйста, потерпите меня!

Все упомянутое в статье работает просто отлично. Но теперь я пытаюсь реализовать исключения 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 и между сервисными и клиентскими приложениями, и, следовательно, они ссылаются на одни и те же классы контрактов данных (Category & Fault)

Скажите, пожалуйста, что я делаю неправильно?

ОБНОВЛЕНИЕ : Я ясно вижу исключение ошибки, отправленное службой в Fiddler. Это заставляет меня поверить, что я что-то упускаю на стороне клиента.

Ответы [ 2 ]

1 голос
/ 03 октября 2011

Чтобы перехватить обычные исключения в sivleright, необходимо создать «Службу WCF с поддержкой Silverlight» (Добавить -> Новый элемент -> Служба WCF с поддержкой Silverlight).Если вы уже создали стандартную службу 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)
    {
    }
}
0 голосов
/ 04 октября 2011

Мы используем наш собственный класс 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);
        }

Затем мы используем универсальный метод для всех вызовов веб-служб:

    /// <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"));
        }
    }
...