【问题标题】:Custom 404 error message in Web API responsesWeb API 响应中的自定义 404 错误消息
【发布时间】:2018-01-21 17:21:41
【问题描述】:

我需要修改 Web API 抛出 404 错误时的消息:

现在,如果任何 api 不存在,让我们说访问 https://mywebsite/api/foo/?%22%26gt;%26lt;script%26gt;_q_q=)(%26lt;/script%26gt

我收到以下回复:

{ "Message": "没有找到与请求 URI 匹配的 HTTP 资源 'https://mywebsite/api/foo/?\">'.", "MessageDetail": "在控制器 'MyController' 上没有发现任何动作 匹配请求。” }

我想修改这条消息。

为了做到这一点,我尝试了这个..

我在控制器上添加了一个自定义属性:

[NoActionFoundFilterAttribute]
public class MyController

过滤器的代码是:

public class NoActionFoundFilterAttribute: ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        // My code
    }
}

在 Web API Config 中我已经添加了过滤器:

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

即使在完成上述所有步骤之后,OnException 调用无效操作时,未命中方法“NoActionFoundFilterAttribute”文件。

您能否分享我缺少的内容以修改自定义 404 错误消息

【问题讨论】:

  • 我不确定其他人是否出于同样的原因来到这里。但是我发现这个问题是因为“未找到”页面可以使用跨站点脚本。开箱即用,我预计这是不可能的!

标签: c# asp.net asp.net-web-api2


【解决方案1】:

我找到了解决办法。

这是我所做的:

我添加了以下行来挂钩到 Web API 响应管道,以获取 Web API 返回的消息:

config.MessageHandlers.Add(new WebApiCustomMessageHandler());

然后我像这样实现了 WebApiCustomMessageHandler:

public class WebApiCustomMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {

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

        if (response.StatusCode == HttpStatusCode.NotFound)
        {
            request.Properties.Remove(HttpPropertyKeys.NoRouteMatched);
            var errorResponse = request.CreateResponse(response.StatusCode, "Content not found.");
            return errorResponse;
        }

        return response;
    }
}

实施上述解决方案后,我能够修改来自 WebAPI 的 ContentNotFound 响应。最终的回应是这样的:

“未找到内容。”

【讨论】:

  • 很好,谢谢。我发现 XSS 对于 404 页面的查询参数似乎可行,这让我感到惊讶。您的回答提供了解决方案。
  • 与@the-senator 相同,如果事情有点不太了解管道,我正在寻找合适的位置来放置这种类型,因为 DelegatingHandler 的文档对理解这个答案很有帮助。
  • @Raghav config.MessageHandlers.Add(new WebApiCustomMessageHandler());这在 .NET Core Web API 中不起作用,您能否建议如何在 .NET Core Web API 应用程序上注册
【解决方案2】:

对于任何寻找答案以自定义 ASP.NET 核心/ASP.NET 5 中状态代码 404 的响应消息的人。我们可以创建一个位于管道末端的中间件

public class ResponseMessageMiddleware
{
    private readonly RequestDelegate _next;

    public ResponseMessageMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        // invoke _next to make the next code run before the response sended
        await _next(httpContext); 
        
        // Make sure the response has not been sent by the controller, 
        // this ensures that the message we are about to send does not 
        // suppress messages from the controller with the same status code
        if (!httpContext.Response.HasStarted)
        {
            switch (httpContext.Response.StatusCode)
            {
                case 404:
                    await httpContext.Response.WriteAsJsonAsync(new
                    {
                        Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4",
                        Title = "Notfound.",
                        Status = 404
                    });

                    return;
            }
        }
    }
}

因为我们必须把中间件放在管道的末端,根据这个图,我们必须先注册中间件。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    // Currently, I don't know what app.UseRouting() does but putting 
    // middleware after app.UseRouting() works
    app.UseMiddleware<ResponseMessageMiddleware>();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints => endpoints.MapControllers());
}

使用这段代码,我们不需要在每个控制器或其他任何东西上放置属性,并且这段代码也适用于其他状态码响应,目前,我用它来处理 401 和 405 响应消息。

【讨论】:

    猜你喜欢
    • 2018-11-13
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    相关资源
    最近更新 更多