假设我有一个包含产品和类别的ASP.Net MVC网站,我想要这些网址......
对于数据库中的每个产品/类别,我保存了slug(或者你称之为的任何东西),比如“super-delicous-apple”或“apples”。
没有模式或正则表达式(我可以看到,无论如何),只允许我通过查看网址来确定它是否是产品或类别。我需要查看数据库才能知道。
有什么好方法可以解决这个问题?
暂时不要使用缓存,刷新路由表等。 :)
如果您觉得这个问题有更合适的标题,请随意编辑我的问题标题 - 这是我能想到的最佳标题。
答案 0 :(得分:2)
我比#1更喜欢你的方法#2。我认为你可以在SlugController中创建一个转到SlugHandler动作的路径(或者你想要称之为的其他任何东西)。你只需要一条路线。
然后你的SlugHandler动作会接受一个slug字符串,然后调用一个方法来确定slug是一个类别还是一个产品。 (你确实说这些是独一无二的,是的?也就是说,不可能同时拥有产品和类别的slug。)从那里,你可以调用相应的Product或Category动作方法,传递slug字符串。
一些代码片段如下:
internal enum SlugType
{
Category,
Product
}
private SlugType DetermineSlugTypeFromSlugName(string slug)
{
// some database magic happens here to return appropriate SlugType
}
public ActionResult SlugHandler(string slug)
{
SlugType slugType = DetermineSlugTypeFromSlugName(slug);
switch (slugType)
{
case SlugType.Category:
return Category(slug);
case SlugType.Product:
return Product(slug);
default:
return SomeErrorAction();
}
}
祝你好运!答案 1 :(得分:2)
以下是您可能希望选择1的方法:
在应用程序启动时,您可以转到数据库并返回所有类别。
从这里开始,您可以使用正则表达式构建路线...
//This has a route constraint in the form of the regex returned from GetMyCategories
routes.MapRoute("Categories",
"{category}",
new { controller = "Product", action = "Category" },
new { category = GetMyCategories() }
);
routes.MapRoute("Product",
"{product}",
new { controller = "Product", action = "Product" }
);
string GetMyCategories()
{
StringBuilder categoriesRegex = new StringBuilder("(");
var categories = GetAllCategoriesFromDb();
categories.ForEach(x=>categoriesRegex.AppendFormat("{0}|", x));
categoriesRegex.Append(")");
return categoriesRegex.ToString();
}
此解决方案的一个主要问题是,如果向数据库添加新类别,则需要重新启动应用程序以刷新路由约束的正则表达式。
关于选项2,我认为Funka的答案已经足够好了。
答案 2 :(得分:0)
/ product / id / 5或 /类别/ ID / 3
也可以使用存储过程返回id以保存一次往返
答案 3 :(得分:0)
我试图在大约一个月前解决同样的问题。我解决的解决方案是使用UrlRewriter HttpModule将URL重写为MVC url。这种映射的一个例子是
<rewrite url="/super-tasty-apple" to="/apple/details/3" />
我将这些网址保存在数据库中。当应用程序启动时,我从数据库中读取所有URL并写出映射到我的web.config。我并不特别喜欢这样做,但它解决了每个请求都必须查询数据库的问题。
如果您的应用程序经常添加/编辑网址,那么这种方法可能不适合您。
如果你决定尝试这种方法,那么HttpModules的顺序就变得很重要了。必须在UrlRoutingModule之前添加UrlRewriter模块。
希望这有帮助。