I have a route defined as:
{theme}/{subtheme}/{urltitle}
for listing article details, and I would like to give the possibility to other people (not developers) to create permalinks for an specific article, as example http://www.whateverdomain/article-about-cars/
:
How can I handle the requests to {theme}/{subtheme}/{urltitle}
to be rewritten to a permalink if there is a permalink for this article?
There are three things you have to do to make this happen:
First, let's start with what information our article needs for us to do this:
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;
}
}
The final piece is the Create/Read capability for users to create permalinks. Note that this is 'bad' from an SEO perspective (the dilution that occurs when more than one link resolves to the same page), but you may want to do it (for whatever reason).
With each approach, make sure you issue a 301 Redirect (RedirectToAction
issues this) to the correct "current" URL. If you do not, you will be punished by the search gods.
Update your Permalink Action to redirect you to the Show
action:
public ActionResult ShowByPermalink(string PermalinkName)
{
var article = ArticleRepository.GetBy(PermalinkName);
return RedirectToAction("Show", article);
}
Now for creating the permalink. This involves adding CR
(of the CRUD
) to a Permalink repository, much like we did before with the article.
Here are some caveats:
{permalinkId}/{permalinkName}
, you must have logic to ensure that all permalinks are unique. IRouteConstraint
) would be a way to check at request time whether or not a user is getting a valid slug right. However, this is more work and leads to more database hits (unless you have a good caching mechanism, but that leads to other potential problems){something}
behavior, as in: http://example.com/something
. Otherwise other routes will hit your permalink route when you don't want that to happen. Don't worry about this if you have a good route constraint in place.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With