ASP.NET Web API从响应中删除HttpError

ASP.NET Web API从响应中删除HttpError,asp.net,asp.net-web-api,response,http-error,Asp.net,Asp.net Web Api,Response,Http Error,我正在使用Microsoft ASP.NET Web API构建RESTful服务 我的问题是当出现错误时(例如400错误请求或404未找到),Web API会将HttpErrors返回给用户 问题是,我不想在响应内容中获取序列化的HttpError,因为它有时提供太多信息,因此它违反了OWASP安全规则,例如: 请求: http://localhost/Service/api/something/5555555555555555555555555555555555555555555555555

我正在使用Microsoft ASP.NET Web API构建RESTful服务

我的问题是当出现错误时(例如400错误请求或404未找到),Web API会将HttpErrors返回给用户

问题是,我不想在响应内容中获取序列化的HttpError,因为它有时提供太多信息,因此它违反了OWASP安全规则,例如:

请求:

http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555
作为回应,我当然得到了400,但有以下内容信息:

{
 "$id": "1",
 "Message": "The request is invalid.",
 "MessageDetail": "The parameters dictionary contains a null entry for parameter 'id'  of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
类似这样的内容不仅表明我的WebService基于ASP.NET WebAPI技术(这还不错),而且还提供了有关我的名称空间、方法名称、参数等的一些信息

我试图在Global.asax中设置IncludeErrorDetailPolicy

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker());
是的,这在某种程度上是好的,现在结果不包含MessageDetail部分,但我仍然不想得到这个HttpError

我还构建了自定义的DelegatingHandler,但它也会影响我自己在控制器中生成的400和404,这是我不希望发生的

我的问题是:
有什么方便的方法可以从响应内容中除去序列化的HttpError吗?我只希望用户返回错误请求的响应代码。

使用自定义IHttpActionInvoker怎么样? 基本上,您只需发送一条空的HttpResponseMessage

下面是一个非常基本的例子:

public class MyApiControllerActionInvoker : ApiControllerActionInvoker
{
    public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
    {
        var result = base.InvokeActionAsync(actionContext, cancellationToken);

        if (result.Exception != null)
        {
            //Log critical error
            Debug.WriteLine("unhandled Exception ");

            return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError));
        }
        else if (result.Result.StatusCode!= HttpStatusCode.OK)
        {
            //Log critical error
            Debug.WriteLine("invalid response status");

            return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode));
        }


        return result;
    }
}

您可以做的另一件与Web Api无关的重要事情是删除过多的asp.net和IIS HTTP头。这是一个很好的解释。

我相信您使用消息处理程序的方法是正确的,因为无论Web API管道中的哪个组件将状态代码设置为4xx,消息处理程序都可以清除响应正文。但是,您确实希望区分您显式设置的组件和其他组件设置的组件。这是我的建议,我承认它有点老套。如果你没有其他更好的解决方案,试试看

ApiController
类中,当抛出
HttpResponseException
时,在请求属性中设置一个标志,如下所示

Request.Properties["myexception"] = true;
throw new HttpResponseException(...);
在消息处理程序中,检查属性,如果设置了属性,则不要清除响应正文

var response = await base.SendAsync(request, cancellationToken);

if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException"))
    response.Content = null;

return response;

您可以通过向HttpRequestMessage添加一个扩展方法来对其进行适当的打包,以便
ApicController
和消息处理程序都不知道我上面使用的硬编码字符串“myException”。

好吧,我想这会很好,但在我的应用程序中,我返回自己的HttpResponseMessages,有时作为400个错误请求,例如,如果有人想向我的数据库插入新记录,他会使用控制器PostNewRecord方法。他插入的记录通过验证传递,如果它检测到某些字段丢失,控制器将返回错误的请求,并显示我自己的消息,说明某些字段为空。在您的解决方案中,MyApiControllerActionInvoker将拦截该响应,并删除我的消息,这是我不希望发生的。我只想删除Web API生成的消息。这当然会起作用,但正如您所说,这是一个修复方案,而不是长期解决方案。