Cornwell
Cornwell

Reputation: 3410

Getting Index to accept optional parameters from route

I have this in my Startup.cs file:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "list",
                template: "{controller=List}/{action=Index}/{username?}");
        });

I want this:

/list/

to return a view.

and this:

/list/random_username.12334

to return another view.

I have this in my ListController.cs:

    public IActionResult Index(string username)
    {
        if (String.IsNullOrEmpty(username))
        {
            ViewData["Message"] = "user index";
        } else {
            ViewData["Message"] = "Hello " + username;
        }

        return View();
    }

But only the index without parameters work. The other one returns 404.

Upvotes: 0

Views: 1558

Answers (2)

Luke Alderton
Luke Alderton

Reputation: 3296

Very old question, but for those that stumble over this one, a simple solution if you don't want to add an attribute to every method is to add another route as a failover as per below:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "page",
        pattern: "{controller}/{action}/{username?}",
        defaults: new { controller = "List", action = "Index" });

    endpoints.MapControllerRoute(
        name: "page",
        pattern: "{controller}/{username?}",
        defaults: new { controller = "List", action = "Index" });
});

The above goes into the Configure(IApplicationBuilder app, IWebHostEnvironment env) method in Startup.cs.

UseEndpoints is an extension method found in the Microsoft.AspNetCore.Builder namespace.

In the failover route definition, username potentially doesn't need to be optional and may result in faster route handling, I would test it out in your particular scenario and find what works best for you.

Note: The solution I tested this in was running .NET 5, I realise the question was asked mainly for .NET Core 1, however given the age of the question and its prominence in Google, this may help others looking for a solution using the more modern approach.

Upvotes: 0

Shyju
Shyju

Reputation: 218732

Look at your route definition.

template: "{controller=List}/{action=Index}/{username?}"

So an ideal url will be list/index/something or list or 'list/index'. but if you try list/index (where you index is the name of a user), how does mvc know you meant the action method name rather than the param value ?

If you really want to support list/someusername, you might consider adding an attribute route on your action method.

[Route("list/{username}")]
public ActionResult Index(string username)
{
  // to do : return something
}

Now you can access yoursite/list/someusername

Upvotes: 2

Related Questions