[英]web API and MVC exception handling
我们目前正在将我们的Web表单系统重新开发为Web API和MVC(这对我们来说是新技术)到目前为止,一切似乎都没问题,但是我们正在努力将Web API应用程序中的错误发送回MVC应用程序。 我们意识到我们需要捕获任何异常,并将这些异常转换为HTTP响应
Web API Product控制器如下所示:
public HttpResponseMessage GetProducts()
{
BAProduct c = new BAProduct();
var d = c.GetProducts();
if (d == null)
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "This is a custom error message");
else
return Request.CreateResponse(HttpStatusCode.OK, d);
}
MVC应用程序将通过以下代码调用Web API: -
public T Get<T>()
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(Config.API_BaseSite);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/myapplicaton/products").Result;
response.EnsureSuccessStatusCode();
T res = response.Content.ReadAsAsync<T>().Result;
return (T)res;
}
}
我们想要实现的是当从MVC应用程序中的Web API收到HTTP错误时,用户被重定向到自定义错误页面,或者在当前视图中显示自定义错误消息(取决于错误)。 我们遇到的问题是: -
如何访问我们发回的自定义错误消息? (从示例代码中这将是“这是一个自定义错误消息”,我们已经通过res中的每个属性并且看不到此消息)
根据状态代码,我们如何捕获并将用户重定向到各个错误页面,即404页面,500页面,并显示已发回的自定义响应消息。 我们一直沿着global.asax路线走下去
protected void Application_Error(object sender, EventArgs e) { Exception exception = Server.GetLastError(); Response.Clear(); HttpException httpException = exception as HttpException;
但是我们的httpExecption总是为NULL
我们搜索过等等,到目前为止,找不到合适的东西,希望有人可以指出我们正确的方向。
你的httpException实例为null的原因是因为response.EnsureSuccessStatusCode();
方法不会抛出HttpException
,这是您试图将其HttpException
转换的内容。 它抛出了一个不同的HttpRequestException
但没有简单的方法来获取更多细节(例如状态代码)。
作为调用此方法的替代方法,您可以测试IsSuccessStatusCode
boolean属性并IsSuccessStatusCode
抛出HttpException
:
public T Get()
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(Config.API_BaseSite);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/myapplicaton/products").Result;
if (!response.IsSuccessStatusCode)
{
string responseBody = response.Content.ReadAsStringAync().Result;
throw new HttpException((int)response.StatusCode, responseBody);
}
T res = response.Content.ReadAsAsync<T>().Result;
return (T)res;
}
}
现在可以在Application_Error
捕获此HttpException
,并根据状态代码继续处理:
protected void Application_Error()
{
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.Clear();
Server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Errors";
routeData.Values["action"] = "Http500";
routeData.Values["exception"] = exception;
Response.StatusCode = 500;
Response.TrySkipIisCustomErrors = true;
if (httpException != null)
{
Response.StatusCode = httpException.GetHttpCode();
switch (Response.StatusCode)
{
case 403:
routeData.Values["action"] = "Http403";
break;
case 404:
routeData.Values["action"] = "Http404";
break;
// TODO: Add other cases if you want to handle
// different status codes from your Web API
}
}
IController errorsController = new ErrorsController();
var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
errorsController.Execute(rc);
}
在这个例子中,我假设你有一个ErrorsController
与各自的动作(Http500,Http403,Http404,...)。 将根据状态代码调用相应的操作,您可以返回不同的视图。
更新:
您可能希望捕获HTTP请求的其他工件(例如原因短语),以便在错误页面中显示它。 在这种情况下,您可以编写自己的异常,其中包含您需要的信息:
public class ApiException : Exception
{
public HttpStatusCode StatusCode { get; set; }
public string Reason { get; set; }
public string ResponseBody { get; set; }
}
你可以抛出:
if (!response.IsSuccessStatusCode)
{
throw new ApiException
{
StatusCode = response.StatusCode,
Reason = response.ReasonPhrase,
ResponseBody = response.Content.ReadAsStringAync().Result,
};
}
然后在Application_Error
使用此自定义异常。
这里解决了上述问题的优秀帖子
它主要有两个主要步骤 -
步骤1:反序列化HTTP错误结果中的响应内容,例如
var httpErrorObject = response.Content.ReadAsStringAsync().Result;
// Create an anonymous object to use as the template for deserialization:
var anonymousErrorObject =
new { message = "", ModelState = new Dictionary<string, string[]>() };
// Deserialize:
var deserializedErrorObject =
JsonConvert.DeserializeAnonymousType(httpErrorObject, anonymousErrorObject);
步骤2:在ModelState Dictionaries Client-Side中添加错误
foreach (var error in apiEx.Errors)
{
ModelState.AddModelError("", error);
}
使用deserializedErrorObject在apiEx.Errors中添加字符串错误消息。
请参阅链接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.