如何允许用户在ASP.NET MVC中创建永久链接?

时间:2011-08-12 11:21:24

标签: asp.net-mvc asp.net-mvc-3

我的路线定义为:

{theme}/{subtheme}/{urltitle}用于列出文章详细信息,我想让其他人(不是开发人员)为特定文章创建永久链接,例如http://www.whateverdomain/article-about-cars/

问题

如果本文有永久链接,如何处理将{theme}/{subtheme}/{urltitle}重写为永久链接的请求?

1 个答案:

答案 0 :(得分:7)

要实现这一目标,您需要做三件事:

  1. 定义一个足够模糊的路由,内部数据库调用可以使用该路径,其中包含一些与该文章相关的特定信息。
  2. 在您的控制器操作中进行数据库调用,不仅允许正常路由,而且也适用于此永久链接(我将在下面向您展示两个不同的控制器)
  3. 创建'CRUD'(或实际上,'CR'是用户创建自己的永久链接并将其存储在数据库字段中所必需的(我也将在下面进行讨论)。
  4. 首先,让我们从我们的文章需要的信息开始:​​

    数据库表结构

    Article
    -------
    Id       <--------- 
    Title              \
    Slug               |
    Theme              |
    SubTheme           |
                       |
                       |
    Permalink Table    |
    ---------------    |
    PermalinkId        |
    Name               |
    Slug               /
    ArticleId ---------
    

    路线

    //normal route for article
    routes.MapRoute("article",
        "{theme}/{subtheme}/{slug}",
        new {controller = "article", action = "show" }
        );
    
    //Permalink route for article
    //You may want to create a custom route constraint for this, or place at bottom of routes
    routes.MapRoute("permalinkArticleRoute",
        "{PermaLinkName}",
        new {controller = "article", action = "showbypermalink"}
        );
    

    控制器

    public class ArticleController : Controller
    {
        public ArticleRepository ArticleRepository {get; set;} //DI'd or constructor injected
        public ActionResult Show(Article article)
        {
            var article = ArticleRepository.GetBy(article.theme, article.subtheme, article.slug);
            ArticleViewModel avm = new ArticleViewModel(article);
            return View(avm);
        }
    
        public ActionResult ShowByPermalink(string PermalinkName)
        {
            var article = ArticleRepository.GetBy(PermalinkName);
            ArticleViewModel avm = new ArticleViewModel(article);
            return View(avm);
        }
    
    }
    

    模型

    public class ArticleRepository
    {
        //Uses Linq-to-SQL. Can be adapted for any other ORM. The retrieval logic is the same
        //It's the actual code that differs
    
        public Article GetBy(string theme, string subtheme, string slug)
        {
            return (from a in db.Articles where
                (a.Theme == theme && a.Subtheme == subtheme && a.Slug == slug)
                select a).FirstOrDefault();
        }
    
        public Article GetBy(string permalinkName)
        {
    
            return (from a in db.Articles 
                join p in Permalink on permaLink.ArticleId equals a.Id
                where p.permalinkName == permalinkName
                select a;
        }
    }
    

    允许用户创建永久链接

    最后一部分是创建/读取功能,供用户创建永久链接。请注意,从SEO角度来看这是“不好的”(当多个链接解析到同一页面时会出现稀释),但您可能想要这样做(无论出于何种原因)。

    对于每种方法,请确保将301重定向(RedirectToAction发出此问题)发布到正确的“当前”网址。如果你不这样做,你将受到搜索神的惩罚。

    更新固定链接操作,将您重定向到Show操作:

        public ActionResult ShowByPermalink(string PermalinkName)
        {
            var article = ArticleRepository.GetBy(PermalinkName);
            return RedirectToAction("Show", article);
        }
    

    现在创建永久链接。这涉及将CRCRUD)添加到Permalink存储库,就像我们之前在文章中所做的那样。

    以下是一些警告:

    • 如果您不使用Url路由{permalinkId}/{permalinkName},则必须具有逻辑以确保所有永久链接都是唯一的。
    • 您需要在行动中加入逻辑来处理404或格式错误的网址。
    • 在创建文章时,您需要使用逻辑来正确地插入文章并将其与文章
    • 一起存储
    • custom route constraint(使用IRouteConstraint)将是一种在请求时检查用户是否获得有效权限的方法。但是,这是更多的工作,并导致更多的数据库命中(除非你有一个很好的缓存机制,但这会导致其他潜在的问题)
    • 如果存在定义{something}行为的其他路由,则您的永久链接路径应位于路径的底部,如:http://example.com/something。否则,当您不希望发生这种情况时,其他路线将会触及永久链接路线。如果您有良好的路线约束,请不要担心这一点。