以正确的方式处理silverlight上的ServiceStack异常
我在获取silverlight端的异常时遇到一些问题 考虑这个简单的例子 服务:以正确的方式处理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
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;
}
}