您好我已经尝试解决一个问题很长一段时间它与路由和链接无关。
我有一个存储大量书籍的应用程序。每本书都有显示其详细信息的链接。为了获得详细信息,我在链接中使用了每本书的ID。这是链接的代码:
@Html.ActionLink(book.Name, "Details", new { bookId = book.Id , book = book.BookUrl })
当用户点击其中一个链接时,这是正在调用的控制器,我不允许修改它:
public ActionResult Details (int bookId){..}
这就是我的链接显示方式:
http://localhost:51208/Home/Details/C-sharp-5.0-in-a-Nutshell-The-Definitive-Reference/BookId-2
我想要的是停止显示控制器动作和BookId。所以我的链接看起来像这样:
http://localhost:51208/C-sharp-5.0-in-a-Nutshell-The-Definitive-Reference
据我所知,到目前为止,使用路由的标准功能无法做到这一点,所以我想我必须以某种方式扩展它的功能。
我一直在PRO ASP.NET MVC 4阅读此内容,根据我的阅读,我必须创建一个类并继承自RouteBase
。
这将导致必须实现两个方法,一个是RouteData GetRouteData(HttpContextBase httpContext)
,另一个是VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
到目前为止,我只知道GetVirtualPath
负责生成链接,因此我认为这是我必须创建实现以获得所需功能的地方。
如果是这种情况,有人可以告诉我如何实施这种方法吗?
如果这不是采取的路线,那么我怎样才能实现我的目标呢?
答案 0 :(得分:2)
您可以在RouteConfig.cs
中添加额外路线,如下所示:
routes.MapRoute(
"Book Details", // Route name
"{ bookName }", // URL with parameters
new { controller = "BookController",
action = "Details",
name = UrlParameter.Optional
} // Parameter defaults
);
相应地更改Details
方法,但其参数必须为bookName
。
注意:
将此路线放在您定义的所有路线的底部,以避免歧义。
答案 1 :(得分:1)
您可以通过实施自己的RouteBase版本来实现此目的。您需要同时实施GetRouteData
和GetVirtualPath
。
您GetRouteData
的实施需要检查您的图书数据库,以查看该网址是否包含数据库中图书的名称,然后返回正确的路线数据,例如
public class BookRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
url = url.Replace(@"~/", "");
var book = getBookWithTheNameThatMatchesTheUrl(url);
if (book != null)
{
var rd = new RouteData(this, new MvcRouteHandler());
rd.Values.Add("controller", "Home");
rd.Values.Add("action", "Details");
rd.Values.Add("bookId", book.Id);
return rd;
}
return null;
}
并且GetVirtualPath
的实现需要反过来 - 找到具有给定ID的书名,并返回相应的URL。
e.g。
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values)
{
if ((string)values["action"] == "Details" &&
(string)values["controller"] == "Home")
{
var bookId = (int)values["bookId"];
var bookName = LookUpTheBookNameForTheBookWithThisId(bookId);
return new VirtualPathData(this, bookName);
}
return null;
}
最后,在注册路由的位置添加routes.Add(new BookRoute());
以启用此新路由。
鉴于方法getBookWithTheNameThatMatchesTheUrl()
将针对每个页面访问数据库,您需要缓存查找。