Jonas Arcangel
Jonas Arcangel

Reputation: 1925

Dynamically Creating Route Parameters in ASP.Net MVC

My requirement is to be able to accept the following combinations

{Part1}/{Controller}/{Action}

{Part1}/{Part2}/{Controller}/{Action}

{Part1}/{Part2}/{Part3}/{Controller}/{Action}

and pass them into controllers and methods that will convert Parts 1 to 3 into an ID that is used all over the system. The scheme is:

string id = part1 + "-" + part2 + "-" + part3

The routes are organized in that way to give the appearance of a folder structure, and the controllers / actions are what's available for those "folders".

I'd like to come up with a way of doing this adhering to DRY.

I'm thinking perhaps this is an Action Filter (which I will apply universally) that creates a new entry ID into the RouteValueDictionary, taking the value from the presence of Parts 1 to 3.

Is this the right approach or is there a better solution?

Thank you.

Upvotes: 1

Views: 999

Answers (1)

Rowan Freeman
Rowan Freeman

Reputation: 16348

Here's an idea.

Create some routes

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Special",
        url: "{part1}/{controller}/{action}"
        );

    routes.MapRoute(
        name: "Special2",
        url: "{part1}/{part2}/{controller}/{action}"
        );

    routes.MapRoute(
        name: "Special3",
        url: "{part1}/{part2}/{part3}/{controller}/{action}"
        );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}",
        defaults: new { controller = "Home", action = "Index" }
        );
}

Example model

[ModelBinder(typeof(SpecialModelBinder))]
public class SpecialModel
{
    public string id { get; set; }
}

Model Binder

public class SpecialModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        SpecialModel model = (SpecialModel)bindingContext.Model;
        model.id = string.Join("-", controllerContext.RouteData.Values
            .Where(x => new string[] { "part1", "part2", "part3" }.Contains(x.Key))
            .Select(x => x.Value)
            );
        bindingContext.ModelMetadata.Model = model;
    }
}

Example Controller

public class ManageController : Controller
{
    public ActionResult Edit(SpecialModel model)
    {
        return View();
    }
}

Samples:

http://www.example.com/style1/Manage/Edit

@Model.Id == "style1"

http://www.example.com/style1/red/Manage/Edit

@Model.Id == "style1-red"

http://www.example.com/style1/red/16/Manage/Edit

@Model.Id == "style1-red-16"

Upvotes: 1

Related Questions