如何使用ASP中的querystring路由URL。净MVC吗?

时间:2021-06-23 04:11:56

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

我正在尝试在MVC中设置一个自定义路由,以以下格式从另一个系统获取URL:

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

. . / ABC / ABC01 ?关键= 123组= 456

The 01 after the second ABC is a step number this will change and the Key and Group parameters will change. I need to route this to one action in a controller with the step number key and group as paramters. I've attempted the following code however it throws an exception:

第二个ABC后面的01是一个步骤号,它会改变,关键字和组参数也会改变。我需要将它路由到控制器中的一个动作,步骤号键和组作为参数。我尝试了以下代码,但是它抛出了一个异常:

Code:

代码:

routes.MapRoute(
    "OpenCase", 
    "ABC/ABC{stepNo}?Key={key}&Group={group}",
    new {controller = "ABC1", action = "OpenCase"}
);

Exception:

例外:

`The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.`

4 个解决方案

#1


36  

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.

ASP。NET MVC将自动将查询字符串参数映射到控制器中方法中的参数。

#2


4  

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

在定义路线时,你不能在路线的开始处使用a / at:

routes.MapRoute("OpenCase",
    "/ABC/{controller}/{key}/{group}", <-- Bad; see / at beginning
    new { controller = "", action = "OpenCase" },
    new { key = @"\d+", group = @"\d+" }
    );

routes.MapRoute("OpenCase",
    "ABC/{controller}/{key}/{group}", <-- Good; No /  at 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}.

看起来你把stepNo和"ABC"放在一起来得到一个ABC1的控制器。这就是为什么我用{controller}替换了URL的那个部分。

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.

由于您还有一个定义“key”和“group”的路由,因此上面的路由还将捕获您的初始URL并将其发送到操作。

#3


1  

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.

没有理由在新的ASP中使用基于querystring的路由。净MVC项目。它对于从经典ASP转换而来的旧项目是有用的。NET项目,你想保存url。

One solution can be attribute routing.

一个解决方案可以是属性路由。

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

另一种解决方案是通过从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 ());
}

#4


0  

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.

您可以通过以下方式在action参数上嵌入查询字符串的检测。

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

我认为最好有一个控制器来处理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.

ModelBinder将{id}值赋给OpenCaseArguments的id字段。set方法处理querystring分割逻辑。

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

继续这样走。注意,在id参数中,路由获取您的querystring。

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.

我已经使用此方法获得了控制器操作上的多个字段的键值。

#1


36  

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.

ASP。NET MVC将自动将查询字符串参数映射到控制器中方法中的参数。

#2


4  

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

在定义路线时,你不能在路线的开始处使用a / at:

routes.MapRoute("OpenCase",
    "/ABC/{controller}/{key}/{group}", <-- Bad; see / at beginning
    new { controller = "", action = "OpenCase" },
    new { key = @"\d+", group = @"\d+" }
    );

routes.MapRoute("OpenCase",
    "ABC/{controller}/{key}/{group}", <-- Good; No /  at 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}.

看起来你把stepNo和"ABC"放在一起来得到一个ABC1的控制器。这就是为什么我用{controller}替换了URL的那个部分。

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.

由于您还有一个定义“key”和“group”的路由,因此上面的路由还将捕获您的初始URL并将其发送到操作。

#3


1  

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.

没有理由在新的ASP中使用基于querystring的路由。净MVC项目。它对于从经典ASP转换而来的旧项目是有用的。NET项目,你想保存url。

One solution can be attribute routing.

一个解决方案可以是属性路由。

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

另一种解决方案是通过从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 ());
}

#4


0  

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.

您可以通过以下方式在action参数上嵌入查询字符串的检测。

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

我认为最好有一个控制器来处理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.

ModelBinder将{id}值赋给OpenCaseArguments的id字段。set方法处理querystring分割逻辑。

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

继续这样走。注意,在id参数中,路由获取您的querystring。

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.

我已经使用此方法获得了控制器操作上的多个字段的键值。