繁体   English   中英

如何在 ASP.NET MVC 中使用查询字符串路由 URL?

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

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

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

第二个 ABC 之后的 01 是一个步骤编号,它会改变,并且键和组参数也会改变。 我需要将其路由到控制器中的一个动作,并使用步骤编号键和组作为参数。 我尝试了以下代码,但它引发了异常:

代码:

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

例外:

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

您不能在路由中包含查询字符串。 尝试这样的路线:

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

然后,在您的控制器上添加一个这样的方法:

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

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

定义路由时,不能在路由开头使用/

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+" }
    );

试试这个:

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

那么您的操作应如下所示:

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

看起来您正在将stepNo和“ABC”放在一起以获得ABC1控制器。 这就是为什么我用{controller}替换了 URL 的那部分。

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

没有理由在新的 ASP.NET MVC 项目中使用基于查询字符串的路由。 它对于从经典 ASP.NET 项目转换而来的旧项目很有用,并且您希望保留 URL。

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

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

并注册您的自定义路由类

public static void RegisterRoutes(RouteCollection routes)
{
  ...

  routes.Add(new MyOldClassicAspRouting ());
}

查询字符串参数通常特定于该控制器和特定应用程序逻辑。

所以如果这不是写在路由规则中会更好,这是通用的。

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

我认为最好有一个控制器来处理 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 将 {id} 值分配给 OpenCaseArguments 的 id 字段。 set 方法处理查询字符串拆分逻辑。

并继续以这种方式路由。 注意路由在 id 参数中获取您的查询字符串。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM