gpt4 book ai didi

asp.net-mvc - 使用处理程序在MVC处理Web API异常

转载 作者:行者123 更新时间:2023-12-03 08:14:46 26 4
gpt4 key购买 nike

我对MVC 4的异常处理有一些疑问。

我已经实现了HandleErrorAttribute并派生了一个新的自定义属性。它真的很好;但我不想每次都重定向用户自定义错误页面。

我在Actions中遇到的一些错误,是从Web API抛出的错误,我想在当前页面向用户显示这些错误。
例如,如果用户想要创建一条记录,但WebAPI因模型状态无效而引发异常,则异常详细信息将以友好的方式显示在“创建” View 中。

但是HandleErrorAttribute默认情况下会重定向Error.cshtml。

我可以处理“ Action ”中的所有异常,但我认为可以有另一种方法。

我也遵循http://www.prideparrot.com/blog/archive/2012/5/exception_handling_in_asp_net_mvc来实现HandleErrorAttribute

 public class CustomHandleErrorAttribute : HandleErrorAttribute {
private readonly ILogger _logger;

public CustomHandleErrorAttribute() {
_logger = new NLogger(typeof(CustomHandleErrorAttribute));
}

public override void OnException(ExceptionContext filterContext) {
if(filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) {
return;
}

if(new HttpException(null, filterContext.Exception).GetHttpCode() != 500) {
return;
}

if(!ExceptionType.IsInstanceOfType(filterContext.Exception)) {
return;
}

// if the request is AJAX return JSON else view.
if(filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest") {
filterContext.Result = new JsonResult {
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new {
error = true,
message = filterContext.Exception.Message
}
};
}
else {
var controllerName = (string)filterContext.RouteData.Values["controller"];
var actionName = (string)filterContext.RouteData.Values["action"];
var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
filterContext.Result = new ViewResult {

ViewName = View,
MasterName = Master,
ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
TempData = filterContext.Controller.TempData
};
}

_logger.Error(filterContext.Exception.Message, filterContext.Exception);

filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;

filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}

我通过HttpClient和包装器类进行了Web API调用。例如,Get请求如下所示。
 public async Task<BrandInfo> Create(BrandInfo entity) {
using(var apiResponse = await base.PostAsync(BaseUriTemplate, entity)) {

if(apiResponse.IsSuccess) {
return apiResponse.Model;
}

throw new HttpApiRequestException(
string.Format(HttpRequestErrorFormat, (int)apiResponse.Response.StatusCode, apiResponse.Response.ReasonPhrase),
apiResponse.Response.StatusCode, apiResponse.HttpError);
}
}

最佳答案

构建一个将包装HttpClient的类,并使用它来调用Web API。
从Web API返回不同的HTTP状态代码,以用于发生重定向的情况(即500-内部服务器错误,或401-未授权)以及要显示模型状态错误的情况(400-错误的请求是我的选择)。
将包装箱中的状态代码处理为:

a)如果要重定向时发生错误(从Web API收到500或401),请抛出适当的异常

b)当您不希望重定向(从Web API接收到400)时,只需从包装类中返回一些响应模型即可在客户端显示

在您的 Controller 中,仅假设您将从HTTP包装器类返回了响应模型,因为异常将使它永远不会返回到 Controller (您将在全局范围内进行处理并进行重定向)。

如果您需要一个代码示例,我可以提供一个,但是我认为您正在寻找的是一般概念而不是具体的代码。

编辑:

在Web API方面:

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
Dictionary<string,string> errors = new Dictionary<string, string>();
foreach (KeyValuePair<string, ModelState> keyValue in actionContext.ModelState)
{
errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage).FirstOrDefault();
}
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, new ApiError(ApiErrorCode.ModelBindingError, errors));
}
}
}

在您的global.asax中:
        GlobalConfiguration.Configuration.Filters.Add(new ModelValidationFilterAttribute());

自定义ApiError:
public class ApiError
{
public ApiErrorCode ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public Dictionary<string, string> ModelStateErrors;
}

在MVC方面,这是您的包装器HttpClient包装器类的外观:
public class RPCService
{

public async Task<RPCResponseModel<T>> GetAsync<T>(string controller, string action, Dictionary<string, string> queryParams, Dictionary<string, string> headers)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("your host goes here");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); /// Tell RPC to return data as json
if (headers != null) foreach (var header in headers) client.DefaultRequestHeaders.Add(header.Key, header.Value);
string query = Query(queryParams);
var response = await client.GetAsync(controller + "/" + action + query);
if (response.IsSuccessStatusCode)
{
return new RPCResponseModel<T>
{
StatusCode = response.StatusCode,
Data = await response.Content.ReadAsAsync<T>()
};
}
else if(response.StatusCode == HttpStatusCode.BadRequest)
{
return new RPCResponseModel<T>
{
Error = await response.Content.ReadAsAsync<RPCErrorModel>(),
StatusCode = response.StatusCode
};
}
else
{
/// throw your exception to handle globally
}
}
}

响应模型为:
public class RPCErrorModel
{
public int Code { get; set; }
public string Message { get; set; }
public Dictionary<string, string> ModelErrors;
}

public class RPCResponseModel
{
public RPCErrorModel Error { get; set; }
public HttpStatusCode StatusCode { get; set; }
}

public class RPCResponseModel<T> : RPCResponseModel
{
public T Data { get; set; }
}

关于asp.net-mvc - 使用处理程序在MVC处理Web API异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15294963/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com