Как создать вспомогательный метод html, похожий на Html.DisplayFor, который будет выглядеть в пользовательской папке - PullRequest
1 голос
/ 02 августа 2011

Моя модель основана на абстрактном базовом классе и выглядит следующим образом:

  • InsurancePolicy (базовый абстрактный класс для всех полисов)
    • VehicleInsurancePolicy
      • AbcInsurancePolicy
      • DefInsurancePolicy
    • HomeInsurancePolicy
    • LifeInsurancePolicy
    • ... и т. Д.

В контроллере у меня есть следующий код для обычных сценариев детализации / списка:

    public ActionResult Details(int id) {
        // actual type is one of the concrete implementations
        InsurancePolicy policy = _repository.Get(id);
        return View(policy);
    }

    public ActionResult List() {
        // a list of concrete implementations
        IList<InsurancePolicy> policies = _repository.GetLatest(20);
        return View(policies);
    }

Details.chstml вызывает только @Html.DisplayForModel(), и ASP.NET MVC фактически выбирает правильное частичное представление из Shared / DisplayTemplates на основе фактического типа (одного из подклассов). Более того, если он не может найти представление с этим именем, он возвращается к шаблону базового класса InsurancePolicy.cshtml . Например, он выберет VehicleInsurancePolicy.cshtml для модели AbcInsurancePolicy, поскольку AbcInsurancePolicy.cshtml не найден; для HomeInsurancePolicy будет выбрано значение по умолчанию InsurancePolicy.cshtml , поскольку в папке DisplayTemplates нет HomeInsurancePolicy.cshtml . Это позволяет мне добавлять другие подтипы InsurancePolicy, не создавая в первую очередь шаблон отображения.

Я хочу иметь подобное поведение для представления списка. В представлении List.cshtml бритвы я бы только зацикливал свои элементы и вызывал что-то вроде Html.ListItemFor (...)

<ul>
@foreach (var policy in Model) {
    @Html.ListItemFor(_ => policy)
 }
</ul>

Как мне создать помощника html.ListItemFor html, который бы смотрел в папку ListItemTemplates и действовал точно как Html.DisplayFor? Есть ли другой способ сделать это?

Примечания: Html.DisplayFor(m => m.Property, templateName) не будет работать, он должен выбирать имя шаблона на основе типа элемента, рекурсивно возвращаться к шаблону базового класса, пока не найдет что-то.

1 Ответ

0 голосов
/ 03 августа 2011

Способ, которым это работает, заключается в том, что шаблоны находятся на основе набора местоположений видов, определенных в механизме представлений.

Что вы можете сделать, это создать свой собственный ViewEngine, унаследовав его от RazorViewEngine и переопределив

   public override ViewEngineResult FindPartialView(
        ControllerContext controllerContext, 
        string partialViewName, 
        bool useCache)

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

Возможно, вы могли бы сделать что-то подобное (althoможет потребоваться настроить его в соответствии с вашим сценарием)

 public override ViewEngineResult FindPartialView(
    ControllerContext controllerContext, 
    string partialViewName, 
    bool useCache)
{
    ViewEngineResult result = null;

    //Get the TypeName that you want to look for
     var typeName = controllerContext.Controller.ViewData.Model.GetType().Name;

     result = base.FindPartialView(
             controllerContext, typeName, useCache);


    //Fall back to default search path if no other view has been selected  
    if (result == null || result.View == null)
    {
        result = base.FindPartialView(
            controllerContext, partialViewName, useCache);
    }

    return result;  
}
...