Строго типизированный T4MVC Action/ActionLink

Я использую T4MVC (к вашему сведению: v2.6.62) в течение достаточно долгого времени, и я постепенно переводим наш код на этот способ работы (меньше зависимости от магических строк ).

Но мне пришлось остановиться, потому что по какой-то причине T4MVC не может переводить объекты в URL-адреса и, похоже, может работать только с примитивными типами (int/string/etc).

Вот пример:

Разбивка маршрута:

/MyController/MyAction/{Number}/{SomeText}

Класс:

namespace MyNamespace
{
  public class MyClass
  {
    public int Number { get; set; }
    public string SomeText { get; set; }
  }
}

Контроллер:

public class MyController
{
  public virtual ActionResult MyAction(MyClass myClass)
  {
    return View();
  }
}

Просмотр:

<%= Html.Action(
  T4MVC.MyController.Actions.MyAction(
    new MyClass()
    {
      Number = 1,
      SomeText = "ABC"
    }
 ) %>

Конечный результат таков:

/MyController/MyAction?myClass=MyNamespace.MyClass

и не

/MyController/MyAction/1/ABC

Кто-нибудь еще сталкивался с этой проблемой? Доступны ли такие URL-адреса T4MVC?

Вопрос также задан на форуме ASP.NET.


person Dan Atkinson    schedule 04.03.2010    source источник


Ответы (2)


Обновление (11 октября 2012 г.): недавно добавлена ​​поддержка развязывания моделей (см. раздел 3.1 в doc) должны охватывать многие из этих случаев.

Исходный ответ:

Копирую свой ответ из ветки форума:

Хм, я думаю, что это еще не придумали. Может быть, в большинстве случаев, когда у людей есть методы Action, которые принимают объект, значения объекта поступают из опубликованных данных формы, а не передаются по URL-адресу? При таком раскладе вопрос не возникает.

Я думаю, что теоретически T4MVC может быть изменен для поддержки этого. Просто нужно продвигать все свойства верхнего уровня объекта как значения маршрута, а не пытаться использовать сам объект (очевидно, что текущее поведение является фиктивным и является результатом простого вызова ToString() вслепую).

Сталкивались ли с этим другие и думали, что это стоит решить?

person David Ebbo    schedule 04.03.2010
comment
Привет Дэвид. Спасибо за ответ. Я предполагаю, что, учитывая 5 голосов за короткий период, это означает, что это, вероятно, желательная функциональность. :-) - person Dan Atkinson; 04.03.2010
comment
Хорошо, внесу в список TODO! :) - person David Ebbo; 05.03.2010
comment
Спасибо! Я нашел бы это особенно полезным, так как я создал несколько результатов ActionResult, таких как PermanentRedirectResult, которые используют действия в стиле T4MVC, и такая функциональность была бы отличной, не только для использования в представлениях! - person Dan Atkinson; 05.03.2010
comment
Привет Дэвид. Есть ли какие-либо обновления по этому поводу? Мне бы очень хотелось увидеть это в других проектах, с которыми я использую T4MVC, но поскольку они используют сложные типы, мне нужно писать это вручную. - person Dan Atkinson; 02.12.2010
comment
Извините, по этому поводу нет обновлений. Но обратите внимание, что дизайн здесь не простой. Кажется произвольным просто взять свойства объекта и преобразовать их в значения маршрута. Что, если бы были и вложенные свойства? Та же проблема повторится на этом уровне. Итак, все сводится к попытке сериализовать произвольные графы объектов как значения маршрута, и я не уверен, что существует общепринятый «правильный» способ сделать это. - person David Ebbo; 06.12.2010
comment
Разве это не просто вопрос слияния объектов и предоставления MVC беспокойства о произвольной сериализации? Я бы подумал, что MVC.Controller.Action(new { Number = 1, SomeText = "ABC", SomeObject = new Finklestein() }) будет точно переводиться в new { controller = "Controller", action = "Action", Number = 1, SomeText = "ABC", SomeObject = new Finklestein() }) ... или, возможно, эквивалент RouteValueDictionary, поскольку это позволяет легко объединять такие свойства. Или я упускаю что-то очевидное? - person Anthony Mills; 23.03.2011
comment
Я обнаружил, что готов приложить усилия, чтобы создать перегрузку метода действия, которая берет все примитивы и создает то, что в противном случае было бы привязанным к модели объектом для передачи реальному методу действия, в интересах сохранения магических струн в страхе. Можно представить случаи, когда это может выйти из-под контроля, но этого должно быть достаточно в 90% случаев. (или 100% реальных случаев, с которыми я сталкивался до сих пор) - person ; 11.10.2012
comment
Я только что добавил обновление к своему ответу, чтобы указать на новую функцию распаковки моделей, которая должна охватывать это. - person David Ebbo; 11.10.2012
comment
@DavidEbbo Зачем нужно писать явные развязчики? Мне также не нужно писать явные связыватели, так почему это не просто работа по обработке каждого члена в том же духе, что и связыватель по умолчанию обрабатывает неизвестные типы, не относящиеся к коллекции, для каждого члена? - person John; 04.11.2014

Если я правильно понял проблему, то следующий синтаксис должен позволить вам обойти проблему.

<%= Html.ActionLink("test", MVC.MyController.MyAction().AddRouteValues(new MyClass() { Number = 5, SomeText = "Hello" })) %>

Я думаю, что ответ, чтобы сделать синтаксис более приятным, состоял бы в том, чтобы обернуть каждый параметр типа значения не в RouteValueDictionary в каждом сгенерированном методе результата действия.

Изменить: (Ответ на комментарий как недостаточно символов)

Ах, хорошо, мне удалось воссоздать простой пример выше, используя этот метод, чтобы указать: /MyController/MyAction/5/Hello в качестве URL-адреса. Я не совсем уверен, как вложенные сложные типы будут работать на практике. Вы можете использовать некоторую рекурсию, чтобы погрузиться в объект верхнего уровня и подумать над значениями, чтобы добавить их, но тогда вы открываете новый набор проблем, например, как справиться с именем дочернего свойства, которое идентично родительскому Имя свойства. Кажется, что это может быть сложная проблема, которую нужно решить таким образом, чтобы это сработало для всех. Возможно, какой-то шаблон адаптера был бы наиболее полезен для преобразования сложного объекта в значения маршрута. В простейшем случае это может быть объявление метода расширения ToRouteDictionary, который воздействует на ваш сложный тип и преобразует его, используя ваши знания о том, как он должен работать. Просто мысли вслух, поскольку я, очевидно, не знаю о ваших вариантах использования

person PabloBlamirez    schedule 08.03.2010
comment
Боюсь, это не работает. Он возвращает значения маршрута, но их URL сформирован неправильно. Кроме того, если это исправлено с помощью этого метода переноса незначащего типа, вам нужно будет сделать это рекурсивно, потому что там вы можете использовать сложный тип, который содержит другие сложные типы... - person Dan Atkinson; 09.03.2010