9

我想处理WebServiceException我的服务客户抛出的所有问题。现在有没有好的方法可以做到这一点?

例如,我在 Windows 窗体应用程序周围传递了一个 ServiceClientBase。我在 http 标头中将 api 密钥传递给服务器。对于任何 API 密钥无效的请求,我想显示一个消息框,告诉用户该请求未经授权,他们应该设置 API 密钥。但我不希望到处都有这段代码:

try
{
    _client.Get(new ReqDto());
}
catch (WebServiceException ex)
{
    if(ex.StatusCode == 401)
        Util.ShowUnauthorizedMessageBox();
}

像这样的东西会很好:

_client.WebServiceExceptionHandler += TheHandler;

我知道我可以连接到本地响应过滤器,但我需要物化 WebServiceException。

我正在查看 ServiceClientBase.cs 以了解我能做什么,但我会很感激任何帮助。谢谢。

4

2 回答 2

2

如果我可以将此作为设计问题而不是 API 问题来处理,那么答案就是包装您的服务客户端。就个人而言,我做了类似的事情,所以我可以在客户端记录服务异常。

这可能是一个起点:

public class MyServiceClient : IDisposable
{
    public ServiceClientBase ServiceClient { get; set; }

    string _serviceUri;
    public string ServiceUri
    {
        get { return _serviceUri; }
        set { _serviceUri = value; ServiceUriChanged(); }
    }

    public MyServiceClient()
    {
        ServiceUri = "http://127.0.0.1:8080";
    }

    public void Dispose()
    {
        ServiceClient.Dispose();
    }

    public TResponse Get<TResponse>(IReturn<TResponse> request)
    {
        try
        {
            return ServiceClient.Get(request);
        }
        catch (WebServiceException ex)
        {
            if(ex.StatusCode == 401)
                Util.ShowUnauthorizedMessageBox();
        }
    }

    void ServiceUriChanged()
    {
        if (ServiceClient != null)
            ServiceClient.Dispose();
        ServiceClient = new JsonServiceClient(ServiceUri);
    }
}

随着时间的推移,您可能会发现这种额外间接级别的其他好处,例如添加本地缓存、记录所有请求和响应 [到调试控制台]。而且,一旦它在您的所有客户端代码中使用,维护起来非常便宜。

就 API 而言,我认为它不能提供您想要的东西。就我个人而言,我对它的原样感到满意(尤其是当IReturn<T>界面有助于整合您想要的功能时)。但是,如果您对它不满意,那么您距离与Demis就改进它的对话仅是一个拉取请求。(-=

于 2013-05-10T19:50:31.537 回答
1

这对游戏来说有点晚了,但我遇到了同样的事情,所以开始挖掘源头。实际上有一个简单的解决方法,覆盖HandleResponseException您正在使用的任何 ServiceClient 中的方法。直接来自评论:

        /// <summary>
        /// Called by Send method if an exception occurs, for instance a System.Net.WebException because the server
        /// returned an HTTP error code. Override if you want to handle specific exceptions or always want to parse the
        /// response to a custom ErrorResponse DTO type instead of ServiceStack's ErrorResponse class. In case ex is a
        /// <c>System.Net.WebException</c>, do not use
        /// <c>createWebRequest</c>/<c>getResponse</c>/<c>HandleResponse&lt;TResponse&gt;</c> to parse the response
        /// because that will result in the same exception again. Use
        /// <c>ThrowWebServiceException&lt;YourErrorResponseType&gt;</c> to parse the response and to throw a
        /// <c>WebServiceException</c> containing the parsed DTO. Then override Send to handle that exception.
        /// </summary>

我个人在覆盖JsonServiceClient

    protected override bool HandleResponseException<TResponse>(Exception ex, object request, string requestUri, Func<System.Net.WebRequest> createWebRequest, Func<System.Net.WebRequest, System.Net.WebResponse> getResponse, out TResponse response)
    {
        Boolean handled;
        response = default(TResponse);
        try
        {
            handled = base.HandleResponseException(ex, request, requestUri, createWebRequest, getResponse, out response);
        }
        catch (WebServiceException webServiceException)
        {
            if(webServiceException.StatusCode > 0)
                throw new HttpException(webServiceException.StatusCode, webServiceException.ErrorMessage);
            throw;
        }
        return handled;
    }
于 2013-09-04T01:54:35.963 回答