ASP Core: how to route to API Controller that is located in the area folder?
Asked Answered
D

2

6

The structure:

+ MyProj
   + Areas
       + Configuration
          - Pages
          - ConfigurationApiController.cs

To create controller without Controllers folder was proposed by VS2017 and it is ok for me since I use Razor Pages and do not need Controllers folder:

enter image description here

Those doesn't work:

Controller defined:

[Route("api")]
[Produces("application/json")]
[ApiController]
public class ConfigurationApiController : ControllerBase
{
    private readonly ApplicationSettings applicationSettings;
    [HttpGet]
    public ActionResult GetUsers()
    {

Mvc routing configured standard way:

app.UseMvc(routes =>
            {

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

How to route to GetUsers action of ConfigurationApiController ?

Doublestop answered 26/1, 2019 at 3:7 Comment(0)
P
6

Modify the api route and add the Area Attribute to provide the area name for [area] route.

    [Area("Configuration")]
    [Route("[area]/api/[controller]")]
    [ApiController]
    public class ConfigurationApiController : ControllerBase
    {
    }

That's all, and it can be accessed at http://localhost:8080/Configuration/api/ConfigurationApi

Publea answered 26/1, 2019 at 11:43 Comment(4)
What is idea of "add the MapRoute for area" ? localhost:8080/Configuration/api/ConfigurationApi works without it, only after area attribute was added.Doublestop
@RomanPokrovskij if you don't define the MapRoute for area, then you are still using the default MapRoute {controller=Home}/{action=Index}/{id?}. Which is in your case, controller = Configuration, action = api, id = ConfigurationApi . If you have Get(int id) method in your controller, check the id value, then you will find out that the id value is "ConfigurationApi"Publea
What drawback could be that I miss routes.MapRoute(name: "areas",... ? Api Controller works without it (because of RouteAttribute?) when razor pages I feel have its own area configuration method: #54380137Doublestop
yes, I think you are correct, there is no need for the MapRoute, if we already defined the area in RouteAttribute. I will update the answer. ThanksPublea
D
3

Some other routing options:

  1. Using AspNetCore.RouteAnalyzer working option found: http://localhost:8080/api (yes, without action)

  2. After removing web APIs attributes

   // [Route("api")]
   // [Produces("application/json")]
   // [ApiController]

then http://localhost:8080/ConfigurationApi/GetUsers

it could be ok but there is no area in the routing and it seems "routing to the area by conventions" doesn't work is asp core: ASP Core: how to configure area for api controller without AreaAttribute (or how to enable convention area routing for Api controller)? and https://github.com/aspnet/AspNetCore/issues/7042

Also in this case ContentResult { Content = json, ContentType = "application/json" } should be return but this is ok for me since I prefer to use in place serialization instead of stream serializers.

  1. This routes to http://localhost:8080/Configuration/api
    [Area("Configuration")]
    [Route("[area]/api")] 
    [Produces("application/json")]
    [ApiController]

other option: [Route("[area]/api/[action]")] routes to http://localhost:8080/Configuration/api/GetUsers

when removing area attribute throws the run-time error Error: While processing template '[area]/api', a replacement value for the token 'area' could not be found. Available tokens: 'action, controller'. To use a '[' or ']' as a literal string in a route or within a constraint, use '[[' or ']]' instead.

    //[Area("Configuration")]
    [Route("[area]/api")]
    [Produces("application/json")]
    [ApiController]

To support @Url.Action(action: "myArea", controller: "myControllerApi") routing should be configured manually.

Asp Core routes:

 app.UseMvc(routes =>
        {
        routes.MapRoute(
        name: "defaultArea",
        template: "{area:exists}/{controller}/{action}"); // matches only those where area route value is defined
        });

Asp Core 3 routes (startup Configure):

 app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllerRoute(
                name: "defaultArea",
                pattern: "{area:exists}/{controller}/{action}");
        });
Doublestop answered 26/1, 2019 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.