C# webapi和MVC异常处理
我们目前正在将我们的web表单系统重新开发为web API和MVC(这对我们来说是一项新技术) 到目前为止,一切似乎都正常,但是我们正在努力将错误从WebAPI应用程序发送回MVC应用程序。我们意识到我们需要捕获任何异常,并将其转换为HTTP响应 Web API产品控制器如下所示:C# webapi和MVC异常处理,c#,asp.net-mvc,asp.net-mvc-4,asp.net-web-api,C#,Asp.net Mvc,Asp.net Mvc 4,Asp.net Web Api,我们目前正在将我们的web表单系统重新开发为web API和MVC(这对我们来说是一项新技术) 到目前为止,一切似乎都正常,但是我们正在努力将错误从WebAPI应用程序发送回MVC应用程序。我们意识到我们需要捕获任何异常,并将其转换为HTTP响应 Web API产品控制器如下所示: public HttpResponseMessage GetProducts() { BAProduct c = new BAProduct(); var d = c.GetP
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;
}
}
然而,我们的httpExecption总是空的
我们已经搜索了etc,到目前为止,还没有找到任何合适的,
希望有人能给我们指出正确的方向。您的httpException实例为空的原因是
响应。EnsureSuccessStatusCode()
方法不会抛出一个HttpException
,而您正试图将其强制转换为该异常。它抛出了一个不同的HttpRequestException
,但是没有简单的方法获取更多细节(例如状态代码)
作为调用此方法的替代方法,您可以测试issucessstatuscode
boolean属性,并自己抛出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;
}
}
在本例中,我假设您有一个带有相应操作的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,
};
}
然后在您的
应用程序中处理此自定义异常\u错误
解决上述问题的一篇优秀文章是
它主要有两个主要步骤-
步骤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);
字符串错误消息添加到apiEx.Errors中,使用deserializedErrorObject
请参见您好,感谢您的快速响应,它非常有用,刚刚经过测试,现在允许我们将用户引导到适当的错误页面,但是,如何在createErrorResponse中获取自定义错误消息?这是否只有在添加了更新后才可能实现?如果是,在中添加此消息有什么意义?再次感谢您测试时发生了什么?是否达到
应用程序\u错误
?是否执行了错误控制器?您是如何定义相应的错误页面的?您是否定义了错误控制器
?您不应该在web.config中定义任何自定义错误,因为在本例中,所有处理都是在Application\u Error
中完成的。它将跳过您可能在那里定义的任何自定义错误页面。您好,感谢您的快速响应,它非常有用,刚刚经过测试,现在允许我们将用户引导到相应的错误页面,但是,如何在createErrorResponse中获取自定义错误消息?这是否只有在添加了更新后才可能实现?如果是,在中添加此消息有什么意义?再次感谢您如果使用HttpException
,则自定义错误消息将出现在ex.message
中。如果使用ApiException
,则它将在ex.Reason
中可用。使用ApiException的目的是,除了错误原因之外,它还允许您捕获响应主体。在HTTP协议中,您可以有状态代码(200,…),原因(状态代码的一些描述)和响应主体。实际上我犯了一个错误。似乎CreateErrorResponse
方法将消息序列化为响应正文的一部分,而不是原因。我会更新我的答案。您可以使用抛出新的HttpException((int)response.StatusCode,response.Content.ReadAsStringAync().Result)代码>以便能够将响应正文作为异常消息传递。然后使用ex.Message
检索它。
if (!response.IsSuccessStatusCode)
{
throw new ApiException
{
StatusCode = response.StatusCode,
Reason = response.ReasonPhrase,
ResponseBody = response.Content.ReadAsStringAync().Result,
};
}
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);
foreach (var error in apiEx.Errors)
{
ModelState.AddModelError("", error);
}