Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8856423
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T14:21:12+00:00 2026-06-14T14:21:12+00:00

Currently I have a controller which looks something like this: public class MyController :

  • 0

Currently I have a controller which looks something like this:

public class MyController : Controller
{
    public ActionResult Action1 (int id1, int id2)
    {

    }

    public ActionResult Action2 (int id3, int id4)
    {

    }
}

As you can see both my controllers have the same parameter “pattern”, two non-nullable signed integers.

My route config looks like this:

routes.MapRoute(
    name: "Action2",
    url: "My/Action2/{id3}-{id4}",
    defaults: new { controller = "My", action = "Action2", id3 = 0, id4 = 0 }
);

routes.MapRoute(
    name: "Action1",
    url: "My/Action1/{id1}-{id2}",
    defaults: new { controller = "My", action = "Action1", id1 = 0, id2 = 0 }
);

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

However, I have a lot more controller actions than just these two, so basically I’ve been mapping a separate route for each one, which strikes me as pretty messy.

What I’m wondering is whether I can do something like the default route with two parameters instead of one, such as:

routes.MapRoute(
    name: "Default2",
    url: "{controller}/{action}/{id1}-{id2}",
    defaults: new { controller = "Home", action = "Index", id1 = 0, id2 = 0 }
);

However, given that my parameters are not always named id1 and id2 this won’t work ( Error is “The parameters dictionary contains a null entry for parameter”. Is there a way I can do this? (Or a completely different way which is better?)

Thanks for the help!

EDIT: Based on the answers thus far it seems my question was a little misleading. I’m wanting a route with generic parameters in particular, so not tied to a specific parameter name.

I want to be able to tell the route manager that “Hey, if you get a request with the pattern {controller}/{action}/{parameter}-{parameter}, I want you to pass those two parameters to the controller and action specified regardless of their type or name!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-14T14:21:14+00:00Added an answer on June 14, 2026 at 2:21 pm

    Well, I decided to expand on Radim’s idea and design my own custom route constraint (mentioned in this question.

    Basically, instead of having many different routes, I now just have one route that matches anything with two integer parameters:

    routes.MapRoute(
        name: "Default2",
        url: "{controller}/{action}/{param1}-{param2}",
        defaults: new { controller = "Admin", action = "Index" },
        constraints: new { lang = new CustomRouteConstraint(new RoutePatternCollection( new List<ParamType> { ParamType.INT, ParamType.INT })) }
    );
    

    In Application_Start() under Global.asax I set the controller namespace for the constraint (which is more efficient than trying to figure it out every time):

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
    
        //should be called before RegisterRoutes
        CustomRouteConstraint.SetControllerNamespace("********.Controllers");
    
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);            
    }
    

    And finally the custom route constraint (I know it’s a ton of code and probably overly complex but I think it’s fairly self explanatory):

    using System;
    using System.Collections.Generic;
    using System.Web.Mvc;
    using System.Web.Routing;
    using System.Web;
    using System.Linq;
    using System.Reflection;
    
    namespace ********.Code
    {
        public class CustomRouteConstraint : IRouteConstraint
        {
            private static string controllerNamespace;
    
            RoutePatternCollection patternCollection { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="CustomRouteConstraint"/> class.
            /// </summary>
            /// <param name="rPC">The route pattern collection to match.</param>
            public CustomRouteConstraint(RoutePatternCollection rPC)
            {
                this.patternCollection = rPC;
    
                if (string.IsNullOrWhiteSpace(controllerNamespace)) {
                    controllerNamespace = Assembly.GetCallingAssembly().FullName.Split(new string[1] {","}, StringSplitOptions.None)
                        .FirstOrDefault().Trim().ToString();
                }
            }
    
            /// <summary>
            /// Sets the controller namespace. Should be called before RegisterRoutes.
            /// </summary>
            /// <param name="_namespace">The namespace.</param>
            public static void SetControllerNamespace(string _namespace)
            {
                controllerNamespace = _namespace;
            }
    
            /// <summary>
            /// Attempts to match the current request to an action with the constraint pattern.
            /// </summary>
            /// <param name="httpContext">The current HTTPContext of the request.</param>
            /// <param name="route">The route to which the constraint belongs.</param>
            /// <param name="paramName">Name of the parameter (irrelevant).</param>
            /// <param name="values">The url values to attempt to match.</param>
            /// <param name="routeDirection">The route direction (this method will ignore URL Generations).</param>
            /// <returns>True if a match has been found, false otherwise.</returns>
            public bool Match(HttpContextBase httpContext, Route route, string paramName, RouteValueDictionary values, RouteDirection routeDirection)
            {
                if (routeDirection.Equals(RouteDirection.UrlGeneration)) {
                    return false;
                }
    
                Dictionary<string, object> unMappedList = values.Where(x => x.Key.Contains("param")).OrderBy(xi => xi.Key).ToDictionary(
                    kvp => kvp.Key, kvp => kvp.Value);
    
                string controller = values["controller"] as string;
                string action = values["action"] as string;
    
                Type cont = TryFindController(controller);
    
                if (cont != null) {
                    MethodInfo actionMethod = cont.GetMethod(action);
    
                    if (actionMethod != null) {
                        ParameterInfo[] methodParameters = actionMethod.GetParameters();
    
                        if (validateParameters(methodParameters, unMappedList)) {
                            for (int i = 0; i < methodParameters.Length; i++) {                            
                                var key = unMappedList.ElementAt(i).Key;
                                var value = values[key];
    
                                values.Remove(key);
                                values.Add(methodParameters.ElementAt(i).Name, value);
                            }
    
                            return true;
                        }
                    }
                }
    
                return false;
            }
    
            /// <summary>
            /// Validates the parameter lists.
            /// </summary>
            /// <param name="methodParameters">The method parameters for the found action.</param>
            /// <param name="values">The parameters from the RouteValueDictionary.</param>
            /// <returns>True if the parameters all match, false if otherwise.</returns>
            private bool validateParameters(ParameterInfo[] methodParameters, Dictionary<string, object> values)
            {
                //@TODO add flexibility for optional parameters
                if (methodParameters.Count() != patternCollection.parameters.Count()) {
                    return false;
                }
    
                for (int i = 0; i < methodParameters.Length; i++) {
                    if (!matchType(methodParameters[i], patternCollection.parameters.ElementAt(i), values.ElementAt(i).Value)) {
                        return false;
                    }
                }
    
                return true;
            }
    
            /// <summary>
            /// Matches the type of the found action parameter to the expected parameter, also attempts data conversion.
            /// </summary>
            /// <param name="actualParam">The actual parameter of the found action.</param>
            /// <param name="expectedParam">The expected parameter.</param>
            /// <param name="value">The value of the RouteValueDictionary corresponding to that parameter.</param>
            /// <returns>True if the parameters match, false if otherwise.</returns>
            private bool matchType(ParameterInfo actualParam, ParamType expectedParam, object value)
            {
                try {
                    switch (expectedParam) {
                        case ParamType.BOOL:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.Boolean":
                                    Convert.ToBoolean(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.DOUBLE:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.Double":
                                    Convert.ToDouble(value);
                                    return true;
                                    break;
                                case "System.Decimal":
                                    Convert.ToDecimal(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.INT:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.Int32":
                                    Convert.ToInt32(value);
                                    return true;
                                    break;
                                case "System.Int16":
                                    Convert.ToInt16(value);                                
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.LONG:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.Int64":
                                    Convert.ToInt64(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.STRING:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.String":
                                    Convert.ToString(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.UINT:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.UInt32":
                                    Convert.ToUInt32(value);
                                    return true;
                                    break;
                                case "System.UInt16":
                                    Convert.ToUInt16(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        case ParamType.ULONG:
                            switch (actualParam.ParameterType.ToString()) {
                                case "System.UInt64":
                                    Convert.ToUInt64(value);
                                    return true;
                                    break;
                                default:
                                    return false;
                                    break;
                            }
                            break;
                        default:
                            return false;
                    }
                } catch (Exception) {
                    return false;
                }
            }
    
            /// <summary>
            /// Attempts to discover a controller matching the one specified in the route.
            /// </summary>
            /// <param name="_controllerName">Name of the controller.</param>
            /// <returns>A System.Type containing the found controller, or null if the contoller cannot be discovered.</returns>
            private Type TryFindController(string _controllerName)
            {
                string controllerFullName;
                Assembly executingAssembly = Assembly.GetExecutingAssembly();
    
                if (!string.IsNullOrWhiteSpace(controllerNamespace)) {
                    controllerFullName = string.Format(controllerNamespace + ".Controllers.{0}Controller", _controllerName);
    
                    Type controller = executingAssembly.GetType(controllerFullName);
    
                    if (controller == null) {
                        if (controllerNamespace.Contains("Controllers")) {
                            controllerFullName = string.Format(controllerNamespace + ".{0}Controller", _controllerName);
    
                            if ((controller = executingAssembly.GetType(controllerFullName)) == null) {
                                controllerFullName = string.Format(controllerNamespace + ".{0}", _controllerName);
    
                                controller = executingAssembly.GetType(controllerFullName);
                            }
                        } else {
                            controllerFullName = string.Format(controllerNamespace + "Controllers.{0}", _controllerName);
    
                            controller = executingAssembly.GetType(controllerFullName);
                        }
                    }
    
                    return controller;
                } else {
                    controllerFullName = string.Format(Assembly.GetExecutingAssembly().FullName.Split(new string[1] {","}, StringSplitOptions.None)
                        .FirstOrDefault().Trim().ToString() + ".Controllers.{0}Controller", _controllerName);
    
                    return Assembly.GetExecutingAssembly().GetType(controllerFullName);
                }            
            }
        }
    
        /// <summary>
        /// A list of the exepected parameters in the route.
        /// </summary>
        public struct RoutePatternCollection
        {
            public List<ParamType> parameters { get; set; }
    
            public RoutePatternCollection(List<ParamType> _params) : this()
            {
                this.parameters = _params;
            }
        }
    
        /// <summary>
        /// The valid parameter types for a Custom Route Constraint.
        /// </summary>
        public enum ParamType
        {
            STRING,
            INT,
            UINT,
            LONG,
            ULONG,
            BOOL,
            DOUBLE
        }
    }
    

    Feel free to suggest improvements if you see them!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a model that looks something like this: public class SampleModel { public
I currently have a login link on my application that looks something like this:
I have a data-structure (in plist) that looks something like this: What i have
Ok, so here's the situation. I currently have a view controller called MainViewController which
I currently have url like localhost/zend_practice/countries/index?data=1 where countries is the name of my controller
I currently have this as a search: <%= form_tag users_path, :controller => 'users', :action
I currently have a Container View Controller which is home to a button. When
I currently have a method in my controller which accepts a form collection, saves
I currently have the following controller method in a Rails app: def index @entries
Here is the thing. I currently have a tabBar controller, with several navigation controllers

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.