基于查询参数的ASP.NET MVC自定义路由
本文关键字:NET ASP MVC 自定义 路由 参数 于查询 查询 | 更新日期: 2023-09-27 18:22:31
我们正在将一个遗留应用程序迁移到.NETMVC,并且必须保持对旧URL的向后兼容性。考虑一个论坛应用程序,其中URL看起来像这个
http://example.com/forums?page=ForumsList - shows a list of all forums
http://example.com/forums?page=Threads&forumId=1 - shows list of threads in forum 1
http://example.com/forums?page=Posts&forumId=1&threadId=1 - shows posts in forum 1, thread 1.
我想将这些相同的URL映射到我的控制器中的操作,即
public ActionResult ForumsList(){}
public ActionResult Threads(string forumId){}
public ActionResult Posts(string forumId, string threadId){}
在不重复我们在遗留系统中的维护噩梦的情况下
public ActionResult Index(string page){
if (page == "Forums"){
return Forums();
}
else if (page == "Threads){
return Threads(Request.Params["forumId"]);
}
else if (page == "Posts"){
return Posts(Request.Params["forumId"], Request.Params["threadId"]);
}
// oh, there's more. a lot more.
}
我能找到的所有关于自定义路由的文档似乎都表明,它只能解析URL的路径部分,而不能解析params。我尝试了以下操作,但没有成功:
routes.MapRoute(
name: "TestRoutes",
url: "{controller}/?page={action}",
defaults: new {controller = "Forums", action = "ForumsList"});
我还能做什么吗?
实际上,您不需要做任何特别的事情。默认情况下,modelbinder将尝试将查询字符串中的任何内容作为参数附加到操作方法。您只需要使用一个操作来处理/代理所有请求:
public class ForumsController : Controller
{
public ActionResult Index(string page, int? forumId, int? threadId)
{
...
}
}
只有默认路线:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
会很好用的。
URL的主位/forums
将与ForumsController
匹配,并且将使用默认操作Index
,因为它没有在URL中指定。id
参数是可选的。然后,querystring中的每个项都将被设置为操作的相同命名参数。forumId
和threadId
参数需要是可以为null的int,以便只为类似/forums?page=ForumsList
URL的内容传递page
参数。
虽然您可以简单地将应用程序设置为以这种方式工作,但我实际上建议将此特定操作保留为交换所。首先,我会创建一个自定义路由,这样您就不必将Index
操作用于以下内容:
routes.MapRoute(
name: "OldForums",
url: "forums",
defaults: new { controller = "OldForums", action = "RedirectToNewURLs" }
);
然后:
public class OldForumsController : Controller
{
public ActionResult RedirectToNewURLs(string page, int? forumId, int? threadId)
{
if (page == "ForumList")
{
return RedirectToActionPermanent("Index", "Forums");
}
if (page == "Threads")
{
return RedirectToActionPermanent("Threads", "Forums", { id = forumId });
}
// etc
}
}
这些重定向会指向你新的不错的论坛URL,比如/forums/{id}/threads
。因此,如果用户通过旧的URL输入,他们只会被重定向到新版本,所有新用户从一开始就被发送到好的URL。
编辑
实际上,我忘了指出,这种方法的一个复杂之处是,您实际上不能将URL /forums
用于实际的论坛索引。你可以使用类似/forums/all
的东西来区分,或者只是做一些类似于奇异化的事情,即forum
。所有其他路由都可以使用forums
前缀,因为只有该字符串本身才能与自定义路由匹配。例如,像forums/1
这样的东西会进入默认路由。