ASP.Net MVC 3 Display-templates и Editor-Template Custom Location, как это сделать? - PullRequest
11 голосов
/ 03 марта 2011

Я иду орехи, я использую MVCContrib, чтобы создать подключаемый сайт с помощью Portable Areas, и пока все работает хорошо, за исключением того, что когда я начал использовать шаблоны MVC, происходит, если я помещаю шаблоны в соответствующую папку View, он работает, примеры

HostApplication/Views/Home/DisplayTemplates/FirstName.cshtml
HostApplication/Areas/PortableArea_Blog/Views/Home/DisplayTemplates/Auther.cshtml

но на самом деле мне нужна возможность создавать общие шаблоны. Задавать и использовать их из хост-приложения или переносимой области, поэтому для этого я создал новую переносимую область, называемую DisplayTemplates (для использования возможности MVCContrib для компиляции представлений), здесь является переносимой зоной структуры

DisplayTemplates
|-Views
  |-CommentTemplate.cshtml

теперь в моем хост-приложении я создал тестовую модель и добавил атрибут UIHint

public class HostModel
    {


        [UIHint("~/Areas/DisplayTemplates/Comment.cshtml")]
        public string Name { get; set; }
    }

но это не работает, поэтому я подумал, что это как-то связано с расположением частичных представлений, поэтому я создал механизм CustomView для поиска частичных представлений в этом расположении и зарегистрировал его в Global.asax, вот краткое представление о том, не утомит вас полным кодом

public class AreaViewEngine : RazorViewEngine
    {
        public AreaViewEngine()
        {

            // {0} = View name
            // {1} = Controller name

            // View locations
            ViewLocationFormats = new[]
                                      {
                                          "~/Areas/DisplayTemplates/{0}.cshtml"

                                      };

            PartialViewLocationFormats = ViewLocationFormats;

            AreaPartialViewLocationFormats = ViewLocationFormats;
        }

        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new RazorView(controllerContext, partialPath, null, true, new[] { "cshtml" });
        }

        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new RazorView(controllerContext, viewPath, masterPath, true, new[] { "cshtml" });
        }




    }

Что еще более странно, так это то, что кажется, что UIHint с явным расположением для Display Template не работает, вот пример

public class HostModel
    {
        //this works
        [UIHint("FirstName")]
        //this does not work
        [UIHint("~/Views/Home/DisplayTemplates/FirstName.cshtml")]
        public string Name { get; set; }
    }

и да

FirstName.cshtml is in HostApplication/Views/Home/DisplayTemplates/FirstName.cshtml

еще раз извините за длинный пост, но я разочаровался в поиске решения, поэтому любая помощь будет полностью оценена.

Ответы [ 5 ]

12 голосов
/ 22 мая 2011

Дэнни прав. Шаблоны находятся так же, как и частичные представления.

По умолчанию WebFormViewEngine и RazorViewEngine будут искать шаблон в следующих местах.

Для шаблонов отображения:

~ / Просмотров / {контроллер} / DisplayTemplates ~ / Views / Shared / DisplayTemplates

Для шаблонов редактора:

~ / Views / {контроллер} / EditorTemplates ~ / Views / Shared / EditorTemplates

Я думаю, что названия подкаталогов (то есть, «DisplayTemplates» и «EditorTemplates») где-то жестко запрограммированы в MVC (я знаю, что это открытый исходный код, и я мог бы его найти, но я не собираюсь) .

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

Допустим, вы хотите, чтобы ваши шаблоны находились в ~ / Views / Templates.

Создайте класс, который наследует от движка представления, который вы используете сейчас (возможно, WebFormViewEngine или RazorViewEngine). Добавьте пустой конструктор. Это должно выглядеть так:

namespace MySite
{
    public class MySiteViewEngine : RazorViewEngine // <<-- or WebFormViewEngine
    {
         public MySiteViewEngine()
         {
             // We'll put some code here in a later step
         }
    }
}

Теперь добавьте следующие строки в метод Application_Start файла Global.asax.cs:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MySiteViewEngine());

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

Но теперь мы хотим добавить местоположение для поиска при поиске PartialViews. Это просто сделать, добавив к PartialViewLocationFormats . Итак, теперь в конструкторе вашего собственного механизма представления вы хотите добавить в массив базового класса примерно так:

base.PartialViewLocationFormats = new string[] {
    "~/Views/Templates/{0}.cshtml"
}.Union(base.PartialViewLocationFormats).ToArray<string>();

Пара замечаний по поводу вышеперечисленного:

  • Приведенная выше запись сделает так, чтобы ваш механизм просмотра искал шаблон отображения String в ~ / Views / Templates / DisplayTemplates / String.cshtml.
  • Формат расположения в этих механизмах просмотра включает расширение файла, поэтому, если вы используете Razor / C #, используйте «cshtml», Razor / VB используйте «vbhtml», WebForms добавьте «aspx» и «ascx».
  • Как я делаю выше, я добавляю свой формат местоположения в начало списка, но сохраняю все местоположения по умолчанию. Вы можете удалить их.
  • Посмотрите текущие форматы, и вы увидите, что вы также получите контроллер в позиции {1} в формате, поэтому, если вы хотите, чтобы под каждым контроллером находился каталог шаблонов.
  • Осторожно, как только вы начинаете перемещать вещи с помощью движка представления, это вызывает привыкание. Вы можете обнаружить, что перемещаете все вокруг.

Удачи.

8 голосов
/ 20 октября 2011

Вместо создания нового ViewEngine вы можете легко изменить существующие во время выполнения:

private void FixMvcTemplateAreaBug(string areaName)
{
    foreach (BuildManagerViewEngine viewEngine in ViewEngines.Engines)
    {
        List<string> viewLocations = 
                     new List<string>(viewEngine.PartialViewLocationFormats);

        foreach (var extension in viewEngine.FileExtensions)
            viewLocations.Add("~/Areas/" + areaName + 
                              "/Views/Shared/{0}." + extension);

        viewEngine.PartialViewLocationFormats = viewLocations.ToArray();
    }
}

Поместите вышеупомянутое в соответствующем месте (например, регистрация области), и все будет в порядке.

2 голосов
/ 02 мая 2011

Я думаю, что у вас нет ответов, потому что их нет: - (

В последние несколько дней я искал максимум и минимум, пытаясь найти решение этой проблемы (поскольку, как вы упомянули,, у него было много просмотров.) К сожалению, я не могу найти способ переопределить это.

Я думаю, что вы застряли: (

Редактировать: Пришелчерез этот пост для чтения представлений из базы данных вместо диска:

ASP.NET MVC загрузить представление Razor из базы данных

Интересно, читаются ли таким образом DisplayTemplatesЕсли это так, вы можете попытаться угнать их и прочитать их из другого места (вместо БД)?

1 голос
/ 14 марта 2014

Это может быть немного поздно :), но теперь это возможно в MVC 4. Общие шаблоны должны быть помещены в ~/Views/Shared/EditorTemplates

Источник

1 голос
/ 19 августа 2013

Простите, если я что-то пропустил выше, но есть ли причина, по которой переопределение Html.DisplayFor, позволяющее указать шаблон, не будет работать здесь?Например:

@Html.DisplayFor(m => m.MyItem, "~/Views/Controller/DisplayTemplates/MyItem.cshtml")

Приветствия,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...