Route action based on HTTP verb?

asp.net-core-mvc

770 观看

1回复

7462 作者的声誉

I'm trying to get ASP.NET Core 2 MVC to route the action based on the HTTP verb via the following code in Startup.cs:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "post",
                template: "api/{controller}/{id?}",
                defaults: new { action = "Post" },
                constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("POST") })
            );
            routes.MapRoute(
                name: "delete",
                template: "api/{controller}/{id?}",
                defaults: new { action = "Delete" },
                constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("DELETE") })
            );
            routes.MapRoute(
                name: "default",
                template: "api/{controller}/{action=Get}/{id?}");
        });

I.e.,

  • If the client calls GET http://example.com/api/foo, that runs the Get() method on my FooController : Controller class.
  • If they call GET http://example.com/api/foo/123, that runs the Get(int id) method on my FooController : Controller class.
  • If they call POST http://example.com/api/foo, that runs the Post([FromBody] T postedItem) method on my FooController<T> : Controller class.
  • If they call POST http://example.com/api/foo/123, that runs the Post(int id, [FromBody] T postedItem) method on my FooController<T> : Controller class.
  • If they call DELETE http://example.com/api/foo/123, that runs the Delete(int id) method on my FooController : Controller

When I run the project, it doesn't seem to run any of my controllers. I have some Razor pages that respond but all of the controller-based routes just return 404. Not even the default route seems to work.

I've been using https://github.com/ardalis/AspNetCoreRouteDebugger to try and help me narrow the issue down but I'm still not finding the problem. It shows the methods on the controllers as available actions but doesn't list any of the names, templates or constraints added via MapRoute. I'd be glad to know of any other helpful tools as well.

FWIW, I'm trying to use the same verb constraints as here: https://github.com/aspnet/Routing/blob/2.0.1/src/Microsoft.AspNetCore.Routing/RequestDelegateRouteBuilderExtensions.cs#L252-L268

作者: steamer25 的来源 发布者: 2017 年 12 月 27 日

回应 1


1

7462 作者的声誉

决定

So I don't recall exactly what the problem turned out to be but the meta-solution is that you can debug routing problems by increasing the log level from "Information" to "Debug". E.g., via appsettings.json:

{
  "Logging": {
    "Debug": {
      "LogLevel": {
        "Default": "Debug"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Debug"
      }
    }
  }
}

...then you'll get messages like this in e.g., the Application Output pane of Visual Studio:

[40m[37mdbug[39m[22m[49m: Microsoft.AspNetCore.Routing.RouteConstraintMatcher[1]
      Route value '(null)' with key 'httpMethod' did not match the constraint 'Microsoft.AspNetCore.Routing.Constraints.HttpMethodRouteConstraint'.
Microsoft.AspNetCore.Routing.RouteConstraintMatcher:Debug: Route value '(null)' with key 'httpMethod' did not match the constraint 'Microsoft.AspNetCore.Routing.Constraints.HttpMethodRouteConstraint'.
[40m[37mdbug[39m[22m[49m: Microsoft.AspNetCore.Routing.RouteBase[1]
      Request successfully matched the route with name 'get' and template 'api/{controller}/{id?}'.
Microsoft.AspNetCore.Routing.RouteBase:Debug: Request successfully matched the route with name 'get' and template 'api/{controller}/{id?}'.
[40m[37mdbug[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action Contoso.Media.ServiceHost.Controllers.MediaController.Get (Contoso.Media.ServiceHost)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Debug: Executing action Contoso.Media.ServiceHost.Controllers.MediaController.Get (Contoso.Media.ServiceHost)
作者: steamer25 发布者: 2018 年 1 月 8 日
32x32