ASP.Net MVC 3 Дисплей-шаблоны и Шаблон-шаблон для пользовательского местоположения, как это сделать?

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

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

но я действительно хочу создать общие шаблоны. Устанавливайте и используйте его из Host Application или Portable Area, поэтому для этого я создал новую Portable Area Called DisplayTemplates (чтобы использовать MVCContrib Ability для компиляции Views), здесь является переносной структурой области

DisplayTemplates
|-Views
  |-CommentTemplate.cshtml

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

public class HostModel
    {


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

но он не работает, поэтому я подумал, что он имеет какое-то отношение к Partial Views Location, поэтому я создал механизм CustomView Engine для поиска Partial Views в этом местоположении и зарегистрировал его в 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 с явным расположением для отображения шаблона не работает, вот пример

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

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

Ответ 1

Дэнни прав. Шаблоны найдены так же, как и Partial Views.

По умолчанию 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());

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

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

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

Несколько примечаний о вышесказанном:

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

Удачи.

Ответ 2

Вместо создания нового 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();
    }
}

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

Ответ 3

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

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Источник