在我的WebApi代码中,我引发了一个HttpResponseException,它将请求管道短路并生成有效的Http响应。但是,我正在尝试将webApi与elmah日志记录集成,但HttpResponseExeptions未显示。
我为elmah设置了web.config并拥有以下代码:
在Global.asx.cs中:
static void ConfigureWebApi(HttpConfiguration config)
{
config.Filters.Add(new ServiceLayerExceptionFilter());
config.Filters.Add(new ElmahHandledErrorLoggerFilter());
config.DependencyResolver = new WebApiDependencyResolver(ObjectFactory.Container);
}
过滤
public class ElmahHandledErrorLoggerFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception);
}
}
引发异常的代码:
public Task<FileUpModel> UploadFile()
{
if (Request.Content.IsMimeMultipartContent())
{
var provider = new TolMobileFormDataStreamProvider("C:\images\");
var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(
t =>
{
if (t.IsFaulted || t.IsCanceled)
throw new HttpResponseException(HttpStatusCode.InternalServerError);
var fileInfo = provider.FileData.FirstOrDefault();
if (fileInfo == null)
// the exception here isn't logged by Elmah?!
throw new HttpResponseException(HttpStatusCode.InternalServerError);
var uploadModel = new FileUpModel { success = true };
return uploadModel;
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
任何实施过这项工作的人都可以让我知道我做错了吗?
答案 0 :(得分:11)
如上所述,当您引发HttpResponseException时,Elmah过滤器不捕获并记录任何内容。更具体地说,如果使用以下语法:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "It was a bad request");
or
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "HttpResponseException - This request is not properly formatted"));
我想在两种情况下陷阱并记录错误。这样做的方法是使用“ActionFilterAttribute”,覆盖“OnActionExecuted”,并检查actionExecutedContext.Response.IsSuccessStatusCode。
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// when actionExecutedContext.Response is null, the error will be caught and logged by the Elmah filter
if ((actionExecutedContext.Response != null) && !actionExecutedContext.Response.IsSuccessStatusCode)
{
try
{
var messages = (System.Web.Http.HttpError)((System.Net.Http.ObjectContent<System.Web.Http.HttpError>)actionExecutedContext.Response.Content).Value;
StringBuilder stringBuilder = new StringBuilder();
foreach (var keyValuePair in messages) {
stringBuilder.AppendLine("Message: Key - " + keyValuePair.Key + ", Value - " + keyValuePair.Value);
}
Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Web API Failed Status Code returned - " + stringBuilder.ToString()));
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Error in OnActionExecuted - " + ex.ToString()));
}
}
}
另外,我还覆盖了“OnActionExecuting”来验证模型状态。这使我可以删除我的行动中的所有检查。
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.ModelState != null && !actionContext.ModelState.IsValid)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (var obj in actionContext.ModelState.Values)
{
foreach (var error in obj.Errors)
{
if(!string.IsNullOrEmpty(error.ErrorMessage)) {
stringBuilder.AppendLine("Error: " + error.ErrorMessage);
}
}
}
Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Invalid Model State -- " + stringBuilder.ToString()));
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
当然,您需要使用“config.Filters.Add”添加过滤器。
答案 1 :(得分:4)
Web API特殊情况HttpResponseException在操作中抛出并转换为HttpResponseMessage,因此您没有看到您的异常过滤器被调用。
在从过滤器中抛出HttpResponseException的情况下,情况并非如此。但是,理想情况下,不需要从过滤器中抛出HttpResponseException,因为您可以通过在提供的输入上下文中设置Response属性来短路请求。
答案 2 :(得分:3)
你需要打开Elmah for HttpFilters才能让它像WebApi一样工作。
使用Elmah.Contrib.WebApi作为NuGet Package,它将连接一个类,然后您可以按照Elmah.Contrib.WebApi项目站点上的说明连接。
如果您想自己这样做,Capturing Unhandled Exceptions in ASP.NET Web API's with ELMAH将引导您了解Elmah.Contrib.WebApi为您做的事情。
此外,我不得不改变错误响应的方式,以便Elmah选择它:
throw new HttpException((int)HttpStatusCode.NotAcceptable, "This request is not properly formatted");
我还建议使用Elmah.MVC NuGet Package。