简体   繁体   中英

ASP.NET Core 3.1 Routing - API and MVC Route confusion

I have two controllers in my application. One is an api controller, the other one a mvc controller. My routes are like this:

api: /api/account/login

mvc: /account/login

My controllers:

[ApiController]
[Route("api/[controller]")]
public class AccountController : ControllerBase
{
    private readonly IMediator _mediator;

    public AccountController(
        IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost("login")]
    public async Task<AuthenticationResultViewModel> Login(LoginRequest loginData, CancellationToken cancellationToken) 
        => await _mediator.Send(loginData, cancellationToken);
}

// this one's in a different namespace
[Route("[controller]")]
public class AccountController : Controller
{
    private readonly IMediator _mediator;

    public AccountController(
        IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet("login")]
    public IActionResult Login([FromQuery] string r)
        => View();

    [HttpPost("login")]
    public async Task<IActionResult> Login([FromQuery] string r, [FromForm] LoginRequest login, CancellationToken cancellationToken)
    {
        await _mediator.Send(login, cancellationToken);

        if (!string.IsNullOrWhiteSpace(r))
            return Redirect(r);
        
        return RedirectToAction("Index", "Home");
    }
}

My ServiceCollection:

//...
services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
services.AddControllersWithViews()
//...

My pipeline is this:

app.UseResponseCaching();
app.UseResponseCompression();

app.UseCors();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

// here i tried defining my routes 
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    // I have tried the following without success
    // I'm actually lost :'(
    //endpoints.MapControllerRoute("mvc", "{controller}/{action}/{id?}", new { controller = "Home", action = "Index" });
    //endpoints.MapControllerRoute("api", "api/{controller}/{action}/{id?}");
});

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.All,
    RequireHeaderSymmetry = false
});

Now my actual problem:

When I use the UrlHelper in my view it always returns the api route!

<form action="@Url.Action("Login", "Account")" method="post">
    <div class="form-group">
        <input asp-for="Username" type="text" placeholder="Username" />
    </div>
    <div class="form-group">
        <input asp-for="Password" type="password" placeholder="Password"/>
    </div>
    <div class="form-group">
        <button type="submit">Login</button>
    </div>
</form>

@Url.Action("Login", "Account") => /api/account/login

  • Why does this happen?
  • How can I make the UrlHelper return my MVC route in my views?

@Url.Action("Login", "Account") => /api/account/login

Why does this happen? How can I make the UrlHelper return my MVC route in my views?

It seems that by using the Url.Action method, it will auto using the API routing, instead of the MVC routing.

To make the UrlHelper return the MVC view, you could use the Url.RouteUrl() method to assign the route Name, or using Url.Content() to set the correct URL. Code as below:

  1. Using the Url.RouteUrl() method :

     <form action="@Url.RouteUrl("defaultmvc", new { controller="Account", action = "Login" })" method="post">

    Code in the StartUp.cs:

     app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "defaultmvc", pattern: "{controller=Home}/{action=Index}/{id?}"); });
  2. Using the Url.Content() method :

     <form action="@Url.Content("~/Account/login")" method="post">

Then, the html resource as below:

       <form action="/Account/login" method="post">
            ...
        </form>

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