简体   繁体   中英

Routing a selection of controller methods to the root URL of the web API

I'm porting a legacy .NET application onto .NET Core Web API.

The legacy application exposes an API that must me ported 1:1.

I've got the following request paths working perfectly fine:

GET https://localhost:5001/MySuperController/user@example.com
GET https://localhost:5001/MySuperController/?username=user@example.com
POST https://localhost:5001/MySuperController/?username=user@example.com

swagger: GET https://localhost:5001/doc

BUT I'm having problems routing the following two paths coming to the root URL:

GET https://localhost:5001/?username=user@example.com
POST https://localhost:5001/?username=user@example.com

This is my controller and swagger registration:

app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
if (EnvironmentConfiguration.EnvironmentType == SystemConstants.DevEnvironment)
{
    app.UseSwagger(s =>
    {
        s.RouteTemplate = "doc/{{documentName}}/docs.json";
    });
    app.UseSwaggerUI(c =>
    {
        c.RoutePrefix = "doc";
        c.SwaggerEndpoint($"../doc/v1/docs.json", "API reference");
    });
}

And this is the controller simplified implementation:

[Route("[controller]")]
[ApiController]
public class MySuperController
{
    // GET https://localhost:5001/MySuperController/user@example.com
    [HttpGet("{emailaddress}")]
    public IActionResult Get(...) {...}

    // GET https://localhost:5001/MySuperController/?username=user@example.com
    [HttpGet()]
    public IActionResult Get(...) {...}

    // POST https://localhost:5001/MySuperController/?username=user@example.com
    [HttpPost()]
    public async Task<IActionResult> Post(...) {...}
}

To support the following two queries, I've added the [Route("")] prefix. But now I'm matching the https://localhost:5001/doc into the first controller action, with {emailaddress} being filled with "doc" .

GET https://localhost:5001/?username=user@example.com
POST https://localhost:5001/?username=user@example.com
[Route("[controller]")]
[Route("")]
[ApiController]
public class MySuperController
{
    // also matches https://localhost:5001/doc now :(
    // GET https://localhost:5001/MySuperController/user@example.com
    [HttpGet("{emailaddress}")]
    public IActionResult Get(...) {...}

    // GET https://localhost:5001/?username=user@example.com
    // GET https://localhost:5001/MySuperController/?username=user@example.com
    [HttpGet()]
    public IActionResult Get(...) {...}

    // POST https://localhost:5001/?username=user@example.com
    // POST https://localhost:5001/MySuperController/?username=user@example.com
    [HttpPost()]
    public async Task<IActionResult> Post(...) {...}
}

What's the most idiomatic way to route these queries correctly with Web API? I would prefer not to split the controller into multiple controllers if at all possible.

Many thanks to Martin Costello's comment, I worked out the following:

[ApiController]
public class MySuperController
{
    [HttpGet("[controller]/{emailaddress}")]
    public IActionResult Get(...) {...}

    [HttpGet("[controller]")]
    [HttpGet("/")]
    public IActionResult Get(...) {...}

    [HttpPost("[controller]")]
    [HttpPost("/")]
    public async Task<IActionResult> Post(...) {...}
}

This way, the GET and POST to / both get resolved with the correct action, while /doc and any other endpoint are not intercepted by the first method, which stays under the controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM