【问题标题】:ASP.NET Web Api returns 200 OK when it should return 404ASP.NET Web Api 在应该返回 404 时返回 200 OK
【发布时间】:2015-04-26 09:38:09
【问题描述】:

我在 ASP.NET Web API 项目中的控制器上有以下操作方法:

[Route("api/v2/project/{projectId}/stuff"), HttpGet]
public IHttpActionResult Get(int projectId)

[Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpGet]
public IHttpActionResult Get(int projectId, [FromUri] Guid id)

[Route("api/v2/project/{projectId}/stuff"), HttpPost]
public IHttpActionResult Post(int projectId, [Required] Stuff stuff)

[Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpPut]
public IHttpActionResult Put(int projectId, [FromUri] Guid blastId, Stuff stuff)

[Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpDelete]
public IHttpActionResult Delete(int projectId, [FromUri] Guid id)

由于 javascript 错误,我向

发出了DELETE 请求
api/v2/project/1234/stuff/undefined

即而不是GUID 的id,我得到了字符串"undefined"。据我所知,这不应该与我的任何路线匹配,但不是404 Not found(甚至405 Method not allowed),而是200 OK 作为响应。

我在每个操作方法中都设置了一个断点,并使用 Fiddler 重复请求,但没有一个断点被命中。我还尝试从 nuget 安装 WebApiRouteDebugger 包,但我们使用的是自定义控制器工厂,它通过我们的 DI 容器连接东西,所以我根本无法让它工作。我什至尝试从我的全局注册过滤器之一中抛出以下异常:

throw new Exception(actionContext.ControllerContext.ControllerDescriptor.ControllerName +
" " + actionContext.ActionDescriptor.ActionName);

DELETE 请求仍然 转到200 OK(似乎没有对有效网址的请求)。

我还能如何解决这个问题?根本原因可能是什么?

【问题讨论】:

  • 我创建了新的 Web APi 项目并添加了带有您的测试方法和路由的控制器。不幸的是工作正常。对于 url 'api/v2/project/{project Id}/stuff/{id:guid}' 我有 404 错误。我认为其他控制器中的路由不正确或 url 与其他路由的“未定义”匹配是问题。
  • @BartoszCzerwonka:非常感谢您抽出时间来做这件事。这个项目很大,这就是为什么我没有在整个项目中包含所有路由 - 但是,我已经仔细检查过,除了这个控制器之外,项目中根本没有匹配api/v2/project/{projectId}/stuff/<anything or nothing>的路由.
  • 此外,其中只有一个应该接受DELETE 请求 - 那是没有命中断点的那个。
  • 您可以发布您的 WebApiConfig.cs 的代码吗?
  • @Josh:我发布了它(带有一些额外的 cmets)here,以避免混淆问题。

标签: asp.net asp.net-web-api routing


【解决方案1】:

我有同样的问题。在我的 startup.cs 中,我有方法

app.Run(async context =>
       {
           context.Response.ContentType = "text/plain";
           await context.Response.WriteAsync("My Api");
       });

这导致所有路由都收到 200 响应以及字符串。 我只想在启动时显示此响应。这就是解决方案。

 app.MapWhen(ctx => ctx.Request.Path.Value == "/", StartupPage);

与同一个 Startup 类中的方法一起

  private void StartupPage(IAppBuilder app)
    {
        app.Run(async (context) =>
        {
            context.Response.ContentType = "text/plain";
            await context.Response.WriteAsync("My Api");
        });
    }

我只在基本 url 上发出请求时返回 200 OK 消息。

【讨论】:

    【解决方案2】:

    我不确定您的路由,但我认为您的路由不包含映射中的操作:

    api/v2/project/1234/stuff/undefined 
    

    为此检查 web api 配置:api/{controller}[/{action}]/{id}。我认为您可能会使用您的操作(例如 GET)触发另一个路由操作。

    附:发布您的路线配置以更新答案。

    【讨论】:

      【解决方案3】:

      在您的 protected void Application_Start(object sender, EventArgs e) 所在的 Global.asax.cs 文件中,添加以下内容:

          protected void Application_BeginRequest(object sender, EventArgs e)
          {
          }
      

      所有服务器请求都应该通过这里。

      如果不存在则添加这些。

      using System.Web.Compilation;
      using System.Reflection;
      

      然后在开始请求调用中添加此代码以列出所有活动路由。

              string Items = "";
              IEnumerable<Assembly> Assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
      
              foreach (Assembly FoundAssembly in Assemblies)
              {
                  string AssemblyName = FoundAssembly.FullName;
                  IEnumerable<TypeInfo> Types = FoundAssembly.DefinedTypes.Where(type => type != null && type.IsPublic && type.IsClass && !type.IsAbstract && typeof(ApiController).IsAssignableFrom(type));
                  foreach (TypeInfo ControllerType in Types)
                  {
                      System.Web.Http.Controllers.ApiControllerActionSelector ApiControllerSelection = new System.Web.Http.Controllers.ApiControllerActionSelector();
                      System.Web.Http.Controllers.HttpControllerDescriptor ApiDescriptor = new System.Web.Http.Controllers.HttpControllerDescriptor(new System.Web.Http.HttpConfiguration(), ControllerType.Name, ControllerType);
                      ILookup<string, System.Web.Http.Controllers.HttpActionDescriptor> ApiMappings = ApiControllerSelection.GetActionMapping(ApiDescriptor);
      
                      foreach (var Maps in ApiMappings)
                      {
                          foreach (System.Web.Http.Controllers.HttpActionDescriptor Actions in Maps)
                          {
                              Items += "[ controller=" + ControllerType.Name + " action=" + ((System.Web.Http.Controllers.ReflectedHttpActionDescriptor)(Actions)).MethodInfo + "]";
                          }
                      }
                  }
              }
      

      这将列出所有控制器及其签名。如果您的 URL 不适合其中任何一个,您可能需要扩展列表以包含非控制器路由。

      【讨论】:

      • 我们项目中的一些其他更改使我无法重现该问题,因为它发生了;但是,这个故障排除建议已经足够好了,如果问题再次出现,我一定会使用它。非常感谢您的提示 - 我很高兴奖励您 1000% 的代表增加 :)
      猜你喜欢
      • 1970-01-01
      • 2019-10-29
      • 2010-09-25
      • 2020-10-02
      • 2015-01-04
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多