Идентификаторы 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