我在Silverlight方面遇到异常时遇到了一些问题...
考虑这个简单的例子
服务:
public void Any(NoResultResponseRequest request)
{
throw new Exception("Someone give me an hug");
}
Dto:
public class NoResultResponseRequest:IReturnVoid
{
public int Id { get;set; }
}
在银光部分:
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
});
}
如果我看着小提琴手的流量,我就有以下的JSon
{"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":[]}}
提前致谢
答案 0 :(得分:3)
如果将EmulateHttpViaPost设置为false,它应该按预期工作...
实际上,如果你切换到http仿真,你必须自己处理WebServiceException,也就是说,Silverlight无法读取非http状态200的http响应。
所以基本上你需要添加一个服务器端过滤器,将http状态代码更改为200
服务器端:
在您的Configure方法中添加: GlobalResponseFilters.Add(HttpOverrideFriendExceptionFilter);
private static void HttpOverrideFriendExceptionFilter(IRequest request, IResponse httpResponse, object response)
{
if (request.Headers[HttpHeaders.XHttpMethodOverride] == null)
{
return;
}
Func<int, string, ResponseError> createRespErr = (statusCode, statusDesc) => new ResponseError
{
ErrorCode = statusCode.ToString(CultureInfo.InvariantCulture),
FieldName = "__HTTP_EXCEPTION",
Message = statusDesc
};
var httpDomainError = response as HttpError;
if (httpDomainError != null)
{
httpResponse.StatusCode = 200;
httpDomainError.ResponseStatus.Errors = new List<ResponseError>();
httpDomainError.ResponseStatus.Errors.Add(createRespErr(httpDomainError.Status, httpDomainError.ErrorCode));
httpDomainError.ResponseStatus.Errors.Add(new ResponseError
{
ErrorCode = httpDomainError.ErrorCode, Message = httpDomainError.Message
});
httpDomainError.StatusCode = HttpStatusCode.OK;
httpResponse.Dto = httpDomainError;
return;
}
var httpResult = response as IHttpResult;
if (httpResult != null)
{
if (httpResult.StatusCode != HttpStatusCode.OK)
{
var errorStatus = httpResult.Status;
var statusDesc = httpResult.StatusDescription;
var respStatus = httpResult.Response.GetResponseStatus() ?? new ResponseStatus
{
Errors = new List<ResponseError>()
};
var errResp = httpResult.Response as ErrorResponse ?? new ErrorResponse
{
ResponseStatus = respStatus
};
httpResult.StatusCode = HttpStatusCode.OK;
httpResult.Response = errResp;
errResp.ResponseStatus.Errors.Add(createRespErr(errorStatus, statusDesc));
}
return;
}
var ex = response as Exception;
if (ex != null)
{
var httpError = new HttpError(HttpStatusCode.OK, ex)
{
StatusCode = HttpStatusCode.OK,
Response = new ErrorResponse
{
ResponseStatus = new ResponseStatus
{
Errors = new List<ResponseError>()
}
}
};
httpError.ResponseStatus.Errors.Add(createRespErr(500, "Unhandle Exception"));
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;
}
}
我知道这有点时髦但是你别无选择,因为Silverlight有很多限制,比如无法读取自定义http标题等等
希望有所帮助
此致