Идентификаторы RavenDB и маршруты ASP.NET MVC3
Просто создайте быстрый, простой сайт с MVC 3 RC2 и RavenDB, чтобы проверить некоторые вещи.
Мне удалось создать кучу проектов, но мне любопытно, как Html.ActionLink() обрабатывает идентификатор БД Raven.
Мой пример: у меня есть документ под названием "причины" (причина для чего-то, только текст в основном), который содержит текст причины и список ссылок. Я могу добавить, удалить и сделать все остальное в моем репозитории.
Ниже приведена часть моего вида бритвы, в которой перечислены все причины в маркированном списке с ссылкой "Изменить" в качестве первого текста:
@foreach(var Reason in ViewBag.ReasonsList)
{
<li>@Html.ActionLink("Edit", "Reasons", "Edit", new { id = Reason.Id }, null) @Reason.ReasonText</li>
<ul>
@foreach (var reasonlink in Reason.ReasonLinks)
{
<li><a href="@reasonlink.URL">@reasonlink.URL</a></li>
}
</ul>
}
Проблема
Это отлично работает, за исключением ссылки на редактирование. Хотя значения и код здесь работают напрямую (т.е. Ссылка запускается напрямую), RavenDB сохраняет мой идентификатор документа как "причины/1".
Итак, когда URL-адрес происходит, и он передает идентификатор, результирующий маршрут "http://localhost: 4976/Причины/Изменить/причины/2". Таким образом, идентификатор добавляется правильно, но MVC интерпретирует его как свой собственный маршрут.
Любые предложения о том, как я могу обойти это? Мне нужно создать специальный маршрут для его обработки или есть что-то еще, что я могу сделать?
Ответы
Ответ 1
Я только что загрузил последнюю версию RavenDB и попробовал это.
public class Entity {
public int Id { get;set; }
public string Text { get;set; }
}
Когда я сохранил его в RavenDB, идентификатор в Raven был "entity/1", но сопоставление в RavenDB-клиенте смогло успешно интерпретировать Id от того, что было в базе данных, к целому числу, которое я хотел.
var entity = session.Load<Entity>(1);
Assert.IsTrue(entity.Id == 1);
Вам не нужен метод расширения, и вам не нужно будет изменять какие-либо маршруты, как указано выше, потому что вы будете иметь дело с хорошими целыми числами. Идентификаторы строк были почти выключателем транзакций, но это удивительно, так что RavenDB вернулся на охоту.
- Примечание. Я понял это, наблюдая за разговором Роба Эштона и понимая, что все его классы документов имеют целые числа в виде идентификаторов.
Ответ 2
У меня была аналогичная проблема и я придумал свое собственное решение, прежде чем нашел ссылку на сообщение в блоге Shiju Varghese, на которое ссылается @jfar.
Это может быть не так просто и просто, как решения, предоставленные в блоге, но я считаю, что он может конкурировать как решение. Итак, вот:
В стандартном классе модели при использовании RavenDB мы обычно имеем свойство id, например:
public string Id { get; set; }
То, что я сделал, заключалось в добавлении другого свойства id так:
public int? IdInt
{
get { return int.Parse(Id.Substring(Id.IndexOf("/") + 1)); }
}
Это даст нам номер части данного идентификатора RavenDB.
Тогда у меня был класс, который выглядел примерно так:
[Bind(Exclude = "IdInt")]
public class Item
{
public string Id { get; set; }
public int? IdInt
{
get { return int.Parse(Id.Substring(Id.IndexOf("/") + 1)); }
}
...
}
Обратите внимание, что я исключил свойство IdInt, так как я не хочу, чтобы привязка к нему обрабатывала.
Кроме того, обратите внимание, что свойство IdInt имеет значение NULL. Это позволит избежать проблем с привязкой к модели позже, когда мы создаем новые элементы, а свойство Id - null.
Затем в маршрутах я объявил правило, подобное этому:
routes.MapRoute(
"WithParam", // Route name
"{controller}/{action}/{id}" // URL with parameters
);
Позже, используя ActionLink или что-то подобное, мы можем сделать следующее:
@Html.ActionLink("Details", "Details", new { id = item.IdInt })
И наконец, когда мы нажимаем отображаемую ссылку, мы отправляем соответствующее действие, которое может выглядеть примерно так:
public ActionResult Details(int id)
{
var item = _session.Load<Item>(id);
return View(item);
}
Причина, по которой это будет работать, - это метод Load, который принимает значение ValueType как параметр, а затем автоматически разрешает номер правильному идентификатору RavenDB.
То, что мы достигли с помощью этого подхода, - это URL-адрес, который выглядит примерно так:
/элементы/детали/1
Как я уже сказал в начале, это решение менее элегантно, чем предыдущие предлагаемые решения, однако этот подход даст вам более чистый URL-адрес, поскольку вы можете работать с идентификатором, как обычно.
Ответ 3
FYI, ссылка, размещенная @jfar, была именно этой статьей. Ниже приведено решение, которое я использовал из статьи:
Решение 2 - Изменить маршрут ASP.NET MVC
Измените маршруты ASP.NET MVC в Файл Global.asax.cs, как показано в следующий код:
routes.MapRoute(
"WithParam", // Route name
"{controller}/{action}/{*id}" // URL with parameters
);
Мы просто положили "*" перед идентификатором переменная, которая будет работать с разделитель Id по умолчанию для RavenDB