servicestack,Silverlight,servicestack" /> servicestack,Silverlight,servicestack" />

以正确的方式处理silverlight上的ServiceStack异常

以正确的方式处理silverlight上的ServiceStack异常,silverlight,servicestack,Silverlight,servicestack,我在获取silverlight端的异常时遇到一些问题 考虑这个简单的例子 服务: public void Any(NoResultResponseRequest request) { throw new Exception("Someone give me an hug"); } Dto: public class NoResultResponseRequest:IReturnVoid { public int Id { get;set; } } 在silverlight

我在获取silverlight端的异常时遇到一些问题

考虑这个简单的例子

服务:

public void Any(NoResultResponseRequest request)
{
   throw new Exception("Someone give me an hug");
}
Dto:

 public class NoResultResponseRequest:IReturnVoid
 {
    public int Id { get;set; }
 }
在silverlight部分:

    private SS.JsonServiceClient  GetService()
    {

        Uri uri = new Uri(App.Current.Host.Source, "../api/");

        var timeout = new TimeSpan(0, 0, 45, 0, 0);// TimeSpan.Parse(ConfigurationManager.AppSettings.Get("servicestackTimeout"));
        SS.JsonServiceClient client = new SS.JsonServiceClient(uri.AbsoluteUri) { Timeout = timeout };

        client.ShareCookiesWithBrowser = true;
        client.StoreCookies = true;
        client.EmulateHttpViaPost = true;

        return client;
    }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var client = GetService();
        var request = new NoResultResponseRequest
        {
            Id = 9
        };

            client.PostAsync(request).ContinueWith(x =>
                {
                  //got a Not found error
                });
    }
如果我和fiddler一起观察交通,我会得到以下结果:

{"responseStatus":{"errorCode":"Exception","message":"Someone give me an hug","stackTrace":"[NoResultResponseRequest: 15/09/2014 11:59:16]:\n[REQUEST: {id:9}]\nSystem.Exception: Someone give me an hug\r\n   at SilverlightException.Web.TestService.Any(NoResultResponseRequest request) in c:\\Projects\\2014\\SilverlightException\\SilverlightException.Web\\TestService.cs:line 14\r\n   at ServiceStack.Host.ServiceExec`1.<>c__DisplayClass6.<CreateExecFn>b__5(Object service, Object request)\r\n   at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)","errors":[]}}
{“responseStatus”:{“errorCode”:“Exception”,“message”:“有人给我一个拥抱”,“stackTrace”:“[NoResultResponseRequest:15/09/2014 11:59:16]:\n[REQUEST:{id:9}]\nSystem.Exception:有人给我一个拥抱\r\n在SilverlightException.Web.TestService.Any(NoResultResponseRequest请求)在c:\\Projects\\2014\\SilverlightException\\SilverlightException.Web\\TestService.cs中:ServiceStack.Host.ServiceExec`1.c\u\u显示类6.b\u 5(对象服务,对象请求)\r\n ServiceStack.Host.ServiceRunner`1.Execute(IRequest请求,对象实例,TRequest请求dto)”,“错误:[]}

提前感谢

如果您将EmulateHttpViaPost设置为false,它将按预期工作

实际上,如果您切换到http仿真,您必须自己处理WebServiceException,也就是说,Silverlight无法读取非http状态200的http响应

因此,基本上您需要添加一个服务器端过滤器,将http状态代码更改为200

服务器端:

在配置方法中添加: 添加(HttpOverrideFriendExceptionFilter)

私有静态无效HttpOverrideFriendExceptionFilter(IRequest请求、IResponse httpResponse、对象响应)
{
if(request.Headers[HttpHeaders.xhttpmethodverride]==null)
{
返回;
}
Func createRespErr=(statusCode,statusDesc)=>new ResponseError
{
ErrorCode=statusCode.ToString(CultureInfo.InvariantCulture),
FieldName=“\uuuuHTTP\uException”,
消息=状态描述
};
var httpDomainError=响应为HttpError;
如果(httpDomainError!=null)
{
httpResponse.StatusCode=200;
httpDomainError.ResponseStatus.Errors=新列表();
httpDomainError.ResponseStatus.Errors.Add(createRespErr(httpDomainError.Status,httpDomainError.ErrorCode));
httpDomainError.ResponseStatus.Errors.Add(新的ResponseError
{
ErrorCode=httpDomainError.ErrorCode,Message=httpDomainError.Message
});
httpDomainError.StatusCode=HttpStatusCode.OK;
httpResponse.Dto=httpDomainError;
返回;
}
var httpResult=响应为IHttpResult;
if(httpResult!=null)
{
if(httpResult.StatusCode!=HttpStatusCode.OK)
{
var errorStatus=httpResult.Status;
var statusDesc=httpResult.StatusDescription;
var respStatus=httpResult.Response.GetResponseStatus()??新建ResponseStatus
{
错误=新列表()
};
var errResp=httpResult.Response as ErrorResponse??新的ErrorResponse
{
ResponseStatus=ResponseStatus
};
httpResult.StatusCode=HttpStatusCode.OK;
httpResult.Response=errResp;
errResp.ResponseStatus.Errors.Add(createRespErr(errorStatus,statusDesc));
}
返回;
}
var ex=异常响应;
如果(ex!=null)
{
var httpError=新的httpError(HttpStatusCode.OK,ex)
{
StatusCode=HttpStatusCode.OK,
响应=新的错误响应
{
ResponseStatus=新ResponseStatus
{
错误=新列表()
}
}
};
httpError.ResponseStatus.Errors.Add(createRespErr(500,“未处理异常”));
httpResponse.Dto=httpError;
}
}
在客户端级别,您需要像这样包装每个调用:

public class SilverlightClient : JsonServiceClient
{
    private const string InternalFieldError = "__HTTP_EXCEPTION";

    public SilverlightClient(string baseUri) 
        : base(baseUri)
    {

    }

    public TResponse SilverlightSend<TResponse>(object requestDto, string httpMethod)
    {
        var r = CustomMethod<HttpWebResponse>(httpMethod, requestDto);
        var text = r.ReadToEnd();

        AssertWebServiceException(text);

        return Deserialize<TResponse>(text);
    }

    public Task<TResponse> SilverlightSendAsync<TResponse>(object request, string httpMethod)
    {
        var task = CustomMethodAsync<HttpWebResponse>(httpMethod, request);
        var tsc = new TaskCompletionSource<TResponse>();

        task.ContinueWith(t =>
        {
            try
            {
                var text = t.Result.ReadToEnd();
                AssertWebServiceException(text);

                if (typeof(TResponse) == typeof(HttpWebResponse))
                {
                    tsc.SetResult((TResponse)(object)t.Result);
                    return;
                }

                tsc.SetResult(Deserialize<TResponse>(text));
            }
            catch (WebServiceException ex)
            {
                tsc.SetException(ex);
            }
            catch (Exception ex)
            {
                tsc.SetException(ex);
            }
        });

        return tsc.Task;
    }

    private void AssertWebServiceException(string text)
    {
        if (text != null && text.IndexOf(InternalFieldError, StringComparison.Ordinal) > -1)
        {
            var errResponse = Deserialize<ErrorResponse>(text);
            ThrowWebServiceException(errResponse);
        }
    }

    private static void ThrowWebServiceException(IHasResponseStatus errorResponse)
    {
        var respStatus = errorResponse.ResponseStatus;
        var serviceEx = new WebServiceException
        {
            StatusCode = 500,
            StatusDescription = respStatus.Message,
            ResponseDto = errorResponse,
        };

        var httpCode = respStatus.Errors.FirstOrDefault(e => e.FieldName == InternalFieldError);
        if (httpCode != null)
        {
            serviceEx.StatusCode = Convert.ToInt32(httpCode.ErrorCode);
            serviceEx.StatusDescription = httpCode.Message;
        }

        throw serviceEx;
    }
}
公共类SilverlightClient:JsonServiceClient
{
私有常量字符串InternalFieldError=“\uuuuHTTP\uException”;
公共SilverlightClient(字符串baseUri)
:base(baseUri)
{
}
公共响应SilverlightSend(对象请求到,字符串httpMethod)
{
var r=CustomMethod(httpMethod,requestDto);
var text=r.ReadToEnd();
AssertWebServiceException(文本);
返回反序列化(文本);
}
公共任务SilverlightSendAsync(对象请求,字符串httpMethod)
{
var task=CustomMethodAsync(httpMethod,请求);
var tsc=new TaskCompletionSource();
task.ContinueWith(t=>
{
尝试
{
var text=t.Result.ReadToEnd();
AssertWebServiceException(文本);
if(typeof(treresponse)=typeof(HttpWebResponse))
{
tsc.SetResult((响应)(对象)t.Result);
返回;
}
tsc.SetResult(反序列化(文本));
}
捕获(WebServiceException ex)
{
tsc.SetException(ex);
}
捕获(例外情况除外)
{
tsc.SetException(ex);
}
});
返回tsc任务;
}
私有void AssertWebServiceException(字符串文本)
{
if(text!=null&&text.IndexOf(InternalFieldError,StringComparison.Ordinal)>-1)
{
var errResponse=反序列化(文本);
ThrowWebServiceException(错误响应);
}
}
私有静态void ThrowWebServiceException(IHasResponseStatus errorResponse)
{
var respStatus=errorResponse.ResponseStatus;
var serviceEx=新的WebServiceException
{
状态代码=500,
StatusDescription=respStatus.Message,
public class SilverlightClient : JsonServiceClient
{
    private const string InternalFieldError = "__HTTP_EXCEPTION";

    public SilverlightClient(string baseUri) 
        : base(baseUri)
    {

    }

    public TResponse SilverlightSend<TResponse>(object requestDto, string httpMethod)
    {
        var r = CustomMethod<HttpWebResponse>(httpMethod, requestDto);
        var text = r.ReadToEnd();

        AssertWebServiceException(text);

        return Deserialize<TResponse>(text);
    }

    public Task<TResponse> SilverlightSendAsync<TResponse>(object request, string httpMethod)
    {
        var task = CustomMethodAsync<HttpWebResponse>(httpMethod, request);
        var tsc = new TaskCompletionSource<TResponse>();

        task.ContinueWith(t =>
        {
            try
            {
                var text = t.Result.ReadToEnd();
                AssertWebServiceException(text);

                if (typeof(TResponse) == typeof(HttpWebResponse))
                {
                    tsc.SetResult((TResponse)(object)t.Result);
                    return;
                }

                tsc.SetResult(Deserialize<TResponse>(text));
            }
            catch (WebServiceException ex)
            {
                tsc.SetException(ex);
            }
            catch (Exception ex)
            {
                tsc.SetException(ex);
            }
        });

        return tsc.Task;
    }

    private void AssertWebServiceException(string text)
    {
        if (text != null && text.IndexOf(InternalFieldError, StringComparison.Ordinal) > -1)
        {
            var errResponse = Deserialize<ErrorResponse>(text);
            ThrowWebServiceException(errResponse);
        }
    }

    private static void ThrowWebServiceException(IHasResponseStatus errorResponse)
    {
        var respStatus = errorResponse.ResponseStatus;
        var serviceEx = new WebServiceException
        {
            StatusCode = 500,
            StatusDescription = respStatus.Message,
            ResponseDto = errorResponse,
        };

        var httpCode = respStatus.Errors.FirstOrDefault(e => e.FieldName == InternalFieldError);
        if (httpCode != null)
        {
            serviceEx.StatusCode = Convert.ToInt32(httpCode.ErrorCode);
            serviceEx.StatusDescription = httpCode.Message;
        }

        throw serviceEx;
    }
}