【问题标题】:Controller refuses to return 404控制器拒绝返回 404
【发布时间】:2017-08-09 16:26:47
【问题描述】:

如何强制我的控制器返回 404?

        [HttpGet]
        [Route("account({accountid})/printgroup", Name = "Get")]
        public HttpResponseMessage Get(int accountid)
        {
            var query = Request.RequestUri.Query;
            var uri = new Uri(Client.Instance.BaseAddress.ToString().Replace("[accountid]", accountid.ToString()) + query);
            var request = new HttpRequestMessage {RequestUri = uri, Method = HttpMethod.Get};
            var clientResponse = Client.Instance.SendAsync(request).Result;
            return clientResponse;
        }

clientResponse 为 404 时,该方法不返回响应。它只是超时。

我做错了什么?如果客户端响应为 404,如何强制它返回 404?

编辑:

根据 macceturra 的有用 cmets,我创建了自己的对象:

但行为是一样的!该方法将超出范围,但客户端看不到任何内容。它只是超时。

我的最新更新是:

    [HttpGet]
    [Route("account({accountid})/bill({billingRunId})", Name = "GetInvoiceSummary")]
    public async Task<IHttpActionResult> GetInvoiceSummary(int accountid, int billingRunId)
    {
        var query = Request.RequestUri.Query;
        var uri = new Uri(Client.Instance.BaseAddress.ToString() + accountid + "/" + billingRunId + query);
        var request = new HttpRequestMessage { RequestUri = uri, Method = HttpMethod.Get };
        var response = await Client.Instance.SendAsync(request);
        if (response.StatusCode == HttpStatusCode.NotFound)
            return NotFound();

        return ResponseMessage(response);

    }

行为再次相同。

【问题讨论】:

  • 您为什么要尝试返回另一个请求的HttpResponse 作为您自己的响应?
  • 您不会在任何地方抛出 404。 WebApi 并不关心 HttpResponseMessage 的属性是否为 = 404。它只是将对象序列化并将其返回给调用者。您应该检查响应,如果您的呼叫响应是 404,则抛出 new HttpNotFoundException()。我要补充一点,返回 HttpResonseMessage 而不是您想要/需要的实际对象似乎是个坏主意。此外,您正在通过不等待异步调用来阻塞线程。
  • @maccettura 为什么我需要等待电话?
  • 在你这样做之前,你的代码不是异步的。
  • 经验法则:如果您在 Task&lt;T&gt; 上调用 .Result,那么您做错了。

标签: c# asp.net .net asp.net-web-api2 visual-studio-2017


【解决方案1】:

更新

根据 cmets 中的讨论,建议您查看响应管道,因为已确定操作中的代码正在按预期处理/执行请求。响应在流出管道时遇到问题,导致客户端超时。检查管道中的消息处理程序和中间件,根据控制器的处理方式,这些处理程序和中间件可能导致响应在流出管道时阻塞。


原答案

考虑以下情况,使用首选的 Web API 2.* 语法以及正确使用 async/await。

[HttpGet]
[Route("account({accountid})/printgroup", Name = "Get")]
public async Task<IHttpActionResult> Get(int accountid) {
    var query = Request.RequestUri.Query;
    var uri = new Uri(Client.Instance.BaseAddress.ToString().Replace("[accountid]", accountid.ToString()) + query);
    var request = new HttpRequestMessage { RequestUri = uri, Method = HttpMethod.Get };
    var clientResponse = await Client.Instance.SendAsync(request);
    if (clientResponse.StatusCode == System.Net.HttpStatusCode.NotFound)
        return NotFound();

    return ResponseMessage(clientResponse);
}

【讨论】:

  • 我确信这会解决这个问题,但没有任何区别:lh3.googleusercontent.com/-vKGL-nbZ_YI/WYuv_DcYjQI/AAAAAAAADbY/…
  • 好吧,最奇怪的。解决问题。请试试这个测试。从该操作中删除所有内容,然后返回 NotFount() 并查看是否出现相同的问题。如果是这样,那么问题就在正在执行的代码之外。消息输出的管道某处存在瓶颈。
  • 将方法签名更改为 IHttpActionResult。删除async Task
  • 但除此之外,您在 web api 管道中遇到了问题。你的代码没有错。出路的管道出现了死锁
【解决方案2】:

添加这块中间件后,问题已解决:

public class NotFoundMiddleware : OwinMiddleware
{
    public NotFoundMiddleware(OwinMiddleware next) : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        await Next.Invoke(context);
        if (context.Response.StatusCode == (int)HttpStatusCode.NotFound
            && !context.Response.Headers.ContainsKey("X-ServiceFabric")
        )
            context.Response.Headers.Add("X-ServiceFabric", new[] { "ResourceNotFound" });
    }
}

【讨论】:

  • 因此我认为问题源于服务结构不知道如何处理导致网关超时的Not Found 响应。
猜你喜欢
  • 2020-10-20
  • 1970-01-01
  • 2021-08-23
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 2019-10-06
相关资源
最近更新 更多