Для этого нужно сделать три вещи:
- Определите достаточно расплывчатый маршрут, который может использоваться внутренним вызовом базы данных с некоторой определенной частью информации, относящейся только к этой статье.
- Выполните вызов базы данных в действии вашего контроллера, чтобы не только разрешить нормальный маршрут, но и эту постоянную ссылку (ниже я покажу вам два различных контроллера)
- Создайте 'CRUD' (или, действительно, 'CR', необходимый пользователям для создания своих собственных постоянных ссылок и сохраните их в поле базы данных (я также рассмотрю это ниже).
Во-первых, давайте начнем с того, какая информация нужна нашей статье для этого:
Структура таблицы базы данных
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
выдает это) на правильный «текущий» URL. Если вы этого не сделаете, вы будете наказаны богами поиска.
Обновите действие Постоянная ссылка, чтобы перенаправить вас на действие Show
:
public ActionResult ShowByPermalink(string PermalinkName)
{
var article = ArticleRepository.GetBy(PermalinkName);
return RedirectToAction("Show", article);
}
Теперь для создания постоянной ссылки. Это включает в себя добавление CR
(из CRUD
) в репозиторий Постоянная ссылка, так же, как мы делали раньше со статьей.
Вот несколько предостережений:
- Если вы не используете URL-маршрут
{permalinkId}/{permalinkName}
, вы должны иметь логику, чтобы гарантировать, что все постоянные ссылки уникальны.
- Вам необходимо включить логику в свои действия, чтобы иметь дело с 404-ми или неправильно сформированными URL-адресами.
- При создании статьи вам нужна логика, чтобы правильно разделить статью и сохранить ее вместе со статьей
- A пользовательское ограничение маршрута (с использованием
IRouteConstraint
) было бы способом проверить во время запроса, получает ли пользователь правильное право на слаг. Однако это больше работы и приводит к большему количеству обращений к базе данных (если у вас нет хорошего механизма кэширования, но это приводит к другим потенциальным проблемам)
- Ваш постоянный маршрут должен находиться внизу ваших маршрутов, если есть другие маршруты, определяющие поведение
{something}
, например: http://example.com/something
. В противном случае другие маршруты попадут на ваш постоянный маршрут, если вы не хотите, чтобы это произошло. Не беспокойтесь об этом, если у вас есть хорошее ограничение маршрута.