Kumar
Kumar

Reputation: 11329

Passing custom arguments to controllers in mvc3

Is there any way to pass arguments to controllers while defining the route table ?

so the same controller can be used for two or more "sections" e.g.

http://site.com/BizContacts   // internal catid = 1 defined in the route        
http://site.com/HomeContacts   // internal catid = 3
http://site.com/OtherContacts   // internal catid = 4

and the controller gets the custom argument defined in the route table to filter and display the data by that additional parameter

so in the example above the index action will be shown and the data shown will be returned by a query such as

 select * from contacts where cat_id = {argument} // 1 or 3 or 4

i hope this is somewhat clear

any help is appreciated ?

Upvotes: 0

Views: 236

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

You could write a custom route:

public class MyRoute : Route
{
    private readonly Dictionary<string, string> _slugs;

    public MyRoute(IDictionary<string, string> slugs)
        : base(
        "{slug}", 
        new RouteValueDictionary(new 
        { 
            controller = "categories", action = "index" 
        }), 
        new RouteValueDictionary(GetDefaults(slugs)), 
        new MvcRouteHandler()
    )
    {
        _slugs = new Dictionary<string, string>(
            slugs, 
            StringComparer.OrdinalIgnoreCase
        );
    }

    private static object GetDefaults(IDictionary<string, string> slugs)
    {
        return new { slug = string.Join("|", slugs.Keys) };
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        if (rd == null)
        {
            return null;
        }
        var slug = rd.Values["slug"] as string;
        if (!string.IsNullOrEmpty(slug))
        {
            string id;
            if (_slugs.TryGetValue(slug, out id))
            {
                rd.Values["id"] = id;
            }
        }
        return rd;
    }
}

which could be registered in Application_Start in global.asax:

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

    routes.Add(
        "MyRoute", 
        new MyRoute(
            new Dictionary<string, string> 
            { 
                { "BizContacts", "1" },
                { "HomeContacts", "3" },
                { "OtherContacts", "4" },
            }
        )
    );

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

and finally you could have your CategoriesController:

public class CategoriesController : Controller
{
    public ActionResult Index(string id)
    {
        ...
    }
}

Now:

  • http://localhost:7060/bizcontacts will hit the Index action of Categories controller and pass id=1
  • http://localhost:7060/homecontacts will hit the Index action of Categories controller and pass id=3
  • http://localhost:7060/othercontacts will hit the Index action of Categories controller and pass id=4

Upvotes: 1

Related Questions