Search code examples
c#asp.net-mvcasp.net-coreasp.net-core-mvcasp.net-mvc-routing

How to validate query string parameters in GET method


I have built an ASP.NET Core MVC application and I have used the default MVC URL routing:

app.UseMvc(routes =>
{
    routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

I want to create the GET method for creating and editing the user.

For creating new user I need to go to url /Admin/User and for editing the existing user url /Admin/User/{id:int}

I have tried to create the method like this:

[HttpGet]
public async Task<IActionResult> User(int? id)
{
}

How can I restrict type of the id parameter?

I need only allow access to /Admin/User or /Admin/User/{id:int} - but if I try i.e. - /Admin/User/ABCD - (use an string as ID) - it is allowed as well.

If the parameter ID will be another type instead of number then I want to return 404.


Solution

  • The simplest option is to create a route with this constraint. Note that if you make the parameter required in the route like this, there is no reason to make id nullable.

    [HttpGet("Admin/User")]
    public async Task<IActionResult> Add()
    {
    }
    
    [HttpGet("Admin/User/{id:int}")]
    public async Task<IActionResult> Edit(int id) 
    {
    }
    

    Or keep the action methods named User and use:

    app.UseMvc(routes =>
    {
        routes.MapRoute("AdminUser", "Admin/User/{id:int}");
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
    

    Note that the convention-based approach doesn't differentiate between GET/POST.

    Alternatively, if you want to make all of your ID parameters an int, you could configure the routing for the whole site like this:

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

    Reference: Routing in ASP.NET Core