ASP Core: how to configure area for api controller

2019-08-20 02:47发布

问题:

Razor Pages do not need any AreaAttribute and it is enough to place them into Areas/MyArea/Pages folder and this is enough to enable routing /MyArea/MyPage

+ My Proj
    + Areas
        + MyArea
            + Pages
                - MyPage.cshtml

But when if I put API Controlller MyApi.cs to MyArea folder:

+ My Proj
    + Areas
        + MyArea
            + Pages
            - MyApi.cs

then I am become forced to "hardcode" area name

[Area("MyArea")] // !!! can't be missed
[Route("[area]/api/[action]")]
[Produces("application/json")]
[ApiController]
public class MyApiController : ControllerBase { // ...

I can't miss/pass AreaAttribute because of 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.

How Razor Pages work without it and how to force MyApiController work without ApiController - just to follow Razor Pages conventions (I want to avoid explicit area hardcoding)?

P.S. for me is ok to remove all "api" attributes not only Area, but also Produces, ApiController... since my api controller's method pass ContentResult { Content = json, ContentType = "application/json" } and I actually do not need theirs functionality.

P.P.S What is interesting that Razor Pages PageModel contains GetArea() method when ControllerBase doesn't. It looks like they have different mechanics of determining the area.

Those options doesn't work:

routes.MapAreaRoute("Configuration", "Configuration", "Configuration/{controller}/{action}");

or

routes.MapRoute("Configuration", "Configuration/{controller}/{action}",
     defaults: new { area = "Configuration" }, 
     constraints: new { area = "Configuration" });

or

routes.MapRoute("Configuration", "Configuration/ConfigurationApi/{action}",
                defaults: new { area = "Configuration", controller = "ConfigurationApi" }, 
                constraints: new { area = "Configuration", controller = "ConfigurationApi" });