Conventional Routing in ASP.NET Core API

大憨熊 提交于 2020-02-28 05:50:19

问题


Problem:

I'm creating an API Application with NET Core 3.1. I'd like to avoid to set route attribute over every ApiControllers and Actions. I tryed a lot of combinations over UseEndpoints to set a conventional route, but i'm failing.

With some configuration I can't get the Api working, with some others I get this exception during startup:

InvalidOperationException: Action 'ApiIsWorking' does not have an attribute route. Action methods on controllers annotated with ApiControllerAttribute must be attribute routed.

How can i set the startup.cs to auto map controllers with their class name and actions with their method name?

Thank you!

Some code:

startup.cs

...
services.AddControllers()
...

app.UseHttpsRedirection()
   .UseRouting()
   .UseAuthentication()
   .UseEndpoints(endpoints => ?? )
   .UseCoreHttpContext()
   .UseServerConfiguration();

controller.cs

[ApiController]
public class BaseAPI : ControllerBase 
{
        [HttpGet]
        public string ApiIsWorking()
        {
            return "API is working!";
        }
}

Solution:

As Reza Aghaei says in the solution, the error was to add the ApiController attribute. After I removed it, the command UseEndpoints start to work.

My mistake was to add the attribute to be able to recognize which classes should be exposed via API. It wasn't necessary because UseEndpoints maps only the classes that inherit from ControllerBase.

Warning:

1) Conventional Routing require [FromBody] attribute in actions params.

2) I highlight Zinov's response about conventional routing problems with Swashbuckle in .NET Core


回答1:


To have conventional routing for your controllers and action, you need to remove [ApiController] attribute and [Route] attribute from your controller and actions and setup route in UseEndpoints.

It's already mentioned in the documentations:

The [ApiController] attribute makes attribute routing a requirement.

Actions are inaccessible via conventional routes defined by UseEndpoints, UseMvc, or UseMvcWithDefaultRoute in Startup.Configure.

Example

This is the working setup that I have for Startup:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

And a sample API controller:

public class ValuesController : ControllerBase
{
    // values/getall
    [HttpGet]
    public IEnumerable<string> GetAll()
    {
        return new string[] { "value1", "value2" };
    }

    // values/getitem/1
    [HttpGet]
    public string GetItem(int id)
    {
        return "value";
    }
}



回答2:


EDIT:

I tried to set it up on my machine. When I removed the Route attribute from controller I got below error:

InvalidOperationException: Action 'WebAPISample.Controllers.WeatherForecastController.Index (WebAPISample)' does not have an attribute route. Action methods on controllers annotated with ApiControllerAttribute must be attribute routed.

The error message itself is saying that the API controllers must use attribute routing.

I know this does not answer your question, but with .NET Core 3 APIs, this does not seem to be possible.

From Documentation:

The [ApiController] attribute makes attribute routing a requirement. For example:

[Route("api/[controller]")] 
[ApiController] 
public class ValuesController : ControllerBase

Actions are inaccessible via conventional routes defined by UseMvc or UseMvcWithDefaultRoute in Startup.Configure.

Refer this page on MSDN.




回答3:


Here is my advice if you are going down this road of using conventional routing with .net core. After you finish your API implementation you are going to add some documentation to it. People normally use this nuget package Swashbuckle.AspNetCore, which implements the later standard of OpenAPI(Swagger). But here is the problem when you use conventional routing and you want to generate the documentation with this tool.

if you are using conventional routing (as opposed to attribute routing), any controllers and the actions on those controllers that use conventional routing will not be represented in ApiExplorer, which means Swashbuckle won't be able to find those controllers and generate Swagger operations from them

For more information refer to this link : Swashbuckle Hope this saves you a lot of headaches in the future with the documentation for your api




回答4:


Have you tried this?

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



来源:https://stackoverflow.com/questions/60205552/conventional-routing-in-asp-net-core-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!