gpt4 book ai didi

asp.net - 如何为 WebApi 管道外的错误返回 JSON?

转载 作者:行者123 更新时间:2023-12-01 11:40:21 24 4
gpt4 key购买 nike

我正在使用 WebApi 2.1 创建一个面向公众的 API,有一个专用的 WebApi 项目(无 MVC),在其自己的服务器上托管在 IIS 7.5 中的 API,并且设计目标是仅返回 JSON或空内容,并且从不返回 HTML

我很高兴地使用 ExceptionFilterAttribute 来处理 WebApi 管道中出现的异常,如下所示:

public class GlobalExceptionHandler : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
// Log the exception to Elmah
Elmah.Error error = new Elmah.Error(context.Exception, HttpContext.Current);
error.Detail = ActionState.GetRequestParameters(context) + error.Detail;
Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(error);

if (context.Exception is NotImplementedException)
{
context.Response = context.Request.CreateErrorResponse(
HttpStatusCode.NotImplemented
, "The API method has not yet been implemented"
);
}
else
{
context.Response = context.Request.CreateErrorResponse(
HttpStatusCode.InternalServerError
, "A " + context.Exception.GetType().ToString() + " was thrown"
);
}

base.OnException(context);
}
}

过滤器已正确添加到 App_Start 中:

config.Filters.Add(new SecureVideoApiGlobalExceptionHandler());

当在 WebApi 管道之外出现错误时,问题就来了。例如,请求带有 Web 根目录的 URI, https://mysite.com/ ,响应是 403.11,HTML 正文指出“Web 服务器配置为不列出此目录的内容。”另一种可能性是在 global.asax 的 Application_Start 方法中调用的代码中存在错误,例如在 AutoMapper 代码中,它断言所有映射都是有效的。

我的问题是:当 API 服务器发生任何错误时,我该如何做到只返回 JSON 错误消息,而不返回 HTML 错误消息?

我试过了

<modules runAllManagedModulesForAllRequests="true">

这允许我处理 global.asax 中 Application_Error() 中的任何错误,但我无法访问那里的 Response 对象以发出 JSON。

最佳答案

你可以做类似这个属性的事情

[AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
public class ExceptionActionFilter : ExceptionFilterAttribute
{
private static Logger _log ;//= LogManager.GetLogger("mysite");

public override void OnException(HttpActionExecutedContext contex)
{
if (_log == null)
_log = LogManager.GetCurrentClassLogger();

var ex = contex.Exception;

_log.Error(ex);

contex.Response = contex.Request.CreateResponse(HttpStatusCode.OK,
new
{
ErrorMessage = contex.Exception.Message,
RealStatusCode = (int)(ex is NotImplementedException || ex is ArgumentNullException ? HttpStatusCode.NoContent : HttpStatusCode.BadRequest),
ReturnUrl = CommonContext.ErrorUrl
},
new JsonMediaTypeFormatter());

base.OnException(contex);
}
}

然后将属性放在类 exc 和客户端

或带过滤器

 public class ExceptionLoggerFilter : System.Web.Http.Filters.IExceptionFilter
{
private static Logger _log;
public ExceptionLoggerFilter()
{
if (_log == null)
_log = LogManager.GetCurrentClassLogger();
}

public bool AllowMultiple { get { return true; } }

public System.Threading.Tasks.Task ExecuteExceptionFilterAsync(
System.Web.Http.Filters.HttpActionExecutedContext contex,
System.Threading.CancellationToken cancellationToken)
{
return System.Threading.Tasks.Task.Factory.StartNew(() =>
{
_log.Error(contex.Exception);

contex.Response = contex.Request.CreateResponse(HttpStatusCode.OK,
new { RealStatusCode = (int)HttpStatusCode.Forbidden, ReturnUrl = "#/error.html"},
contex.ActionContext.ControllerContext.Configuration.Formatters.JsonFormatter);

}, cancellationToken);
}
}

然后在 Global.asax.cs 中

protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
Database.SetInitializer<MySiteContext>(null);
}

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)//RouteCollection config)//
{
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
config.Filters.Add(new ExceptionLoggerFilter());
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });

}
}

在客户端可能是这样的

$.controller.ajax.promise = controller.ajax.promise = function ( obj )
{
var deferred = q.defer();
$.ajax( {
type: obj.type || "GET",
url: obj.url,
context: obj.context || null,
data: obj.data || null,
contentType: obj.contentType || "application/json; charset=utf-8",
dataType: obj.dataType || "json",
success: function ( res, textStatus, jqXHR )
{
if ( res.RealStatusCode )
{
switch ( res.RealStatusCode )
{
case 400://x error
res.ClientMessage = res.ErrorMessage;
deferred.reject(res);
break;
case 408://y errors
location.href = res.ReturnUrl;
return false;
case 403://ext
msgbox.alert( {
message: 'Ma belle msg',
title: "Error"
} );
deferred.reject();
location.href = res.ReturnUrl;
return false;
default:
deferred.reject();
location.href = res.ReturnUrl;
break;
}
}
deferred.resolve( res );
return true;
},
error: function ( jqXHR, textStatus, errorThrown )
{
deferred.reject( { msg: jqXHR.statusText, jqXHR: jqXHR, textStatus:textStatus, errorThrown:errorThrown } );
}
} );

return deferred.promise;
};

我希望这对其他 google 员工有帮助! (就像@Thomas C. G. de Vilhena 说的=)

关于asp.net - 如何为 WebApi 管道外的错误返回 JSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21580861/

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