How do I route a URL with a querystring in ASP.NET MVC?

前端 未结 4 1544
有刺的猬
有刺的猬 2020-11-28 15:28

I\'m trying to setup a custom route in MVC to take a URL from another system in the following format:

../ABC/ABC01?Key=123&Group=456

The 01

相关标签:
4条回答
  • 2020-11-28 16:04

    The query string arguments generally are specific of that controller and of that specific application logic.

    So it will better if this isn't written in route rules, that are general.

    You can embed detection of query string on action argument in the following way.

    I think that is better to have one Controller for handling StepNo.

    public class ABC : Controller
    {
        public ActionResult OpenCase(OpenCaseArguments arg)
        {
            // do stuff here
            // use arg.StepNo, arg.Key and arg.Group as You need
            return View();
        }        
    }
    
    public class OpenCaseArguments
    {
        private string _id;
        public string id
        {
            get
            {
                return _id;
            }
    
            set
            {
                _id = value; // keep original value;
                ParseQueryString(value);
            }
        }
    
        public string  StepNo { get; set; }
        public string Key { get; set; }
        public string Group { get; set; }
    
        private void ParseQueryString(string qs)
        {
            var n = qs.IndexOf('?');
            if (n < 0) return;
            StepNo = qs.Substring(0, n); // extract the first part eg. {stepNo}
            NameValueCollection parms = HttpUtility.ParseQueryString(qs.Substring(n + 1));
            if (parms.Get("Key") != null) Key = parms.Get("Key");
            if (parms.Get("Group") != null) Group = parms.Get("Group");
        }
    
    }
    

    ModelBinder assign {id} value to the id field of OpenCaseArguments. The set method handle querystring split logic.

    And keep routing this way. Note routing get your querystring in id argument.

    routes.MapRoute(
        "OpenCase", 
        "ABC/OpenCase/{id}",
        new {controller = "ABC", action = "OpenCase"}
    );
    

    I have used this method for getting multiple fields key value on controller action.

    0 讨论(0)
  • 2020-11-28 16:15

    When defining routes, you cannot use a / at the beginning of the route:

    routes.MapRoute("OpenCase",
        "/ABC/{controller}/{key}/{group}", // Bad. Uses a / at the beginning
        new { controller = "", action = "OpenCase" },
        new { key = @"\d+", group = @"\d+" }
        );
    
    routes.MapRoute("OpenCase",
        "ABC/{controller}/{key}/{group}",  // Good. No / at the beginning
        new { controller = "", action = "OpenCase" },
        new { key = @"\d+", group = @"\d+" }
        );
    

    Try this:

    routes.MapRoute("OpenCase",
        "ABC/{controller}/{key}/{group}",
        new { controller = "", action = "OpenCase" },
        new { key = @"\d+", group = @"\d+" }
        );
    

    Then your action should look as follows:

    public ActionResult OpenCase(int key, int group)
    {
        //do stuff here
    }
    

    It looks like you're putting together the stepNo and the "ABC" to get a controller that is ABC1. That's why I replaced that section of the URL with {controller}.

    Since you also have a route that defines the 'key', and 'group', the above route will also catch your initial URL and send it to the action.

    0 讨论(0)
  • 2020-11-28 16:17

    There is no reason to use routing based in querystring in new ASP.NET MVC project. It can be useful for old project that has been converted from classic ASP.NET project and you want to preserve URLs.

    One solution can be attribute routing.

    Another solution can be in writting custom routing by deriving from RouteBase:

    public class MyOldClassicAspRouting : RouteBase
    {
    
      public override RouteData GetRouteData(HttpContextBase httpContext)
      {
        if (httpContext.Request.Headers == null) //for unittest
          return null;
    
        var queryString = httpContext.Request.QueryString;
    
        //add your logic here based on querystring
        RouteData routeData = new RouteData(this, new MvcRouteHandler());
        routeData.Values.Add("controller", "...");
        routeData.Values.Add("action", "...");
      }
    
      public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
      {
         //Implement your formating Url formating here
         return null;
      }
    }
    

    And register your custom routing class

    public static void RegisterRoutes(RouteCollection routes)
    {
      ...
    
      routes.Add(new MyOldClassicAspRouting ());
    }
    
    0 讨论(0)
  • 2020-11-28 16:25

    You cannot include the query string in the route. Try with a route like this:

    routes.MapRoute("OpenCase", "ABC/ABC{stepNo}",
       new { controller = "ABC1", action = "OpenCase" });
    

    Then, on your controller add a method like this:

    public class ABC1 : Controller
    {
        public ActionResult OpenCase(string stepno, string key, string group)
        {
            // do stuff here
            return View();
        }        
    }
    

    ASP.NET MVC will automatically map the query string parameters to the parameters in the method in the controller.

    0 讨论(0)
提交回复
热议问题