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

В настоящее время я собираю многопользовательское веб-приложение с использованием MVC 3. По крайней мере, 30 различных веб-сайтов будут иметь общую кодовую базу, и, хотя они также имеют схожие внутренние функции, они должны выглядеть значительно по-разному. Как следствие, я использую URL-адрес для внутреннего разделения клиентов и переопределенный механизм представления Razor (по крайней мере, с точки зрения поиска представления) для автоматического выбора либо настроенного представления для данного действия, либо представления по умолчанию.

Чтобы помочь «разделить» сложную страницу, любое конкретное представление будет использовать несколько частей, обычно отображаемых как автономные действия, так что, как правило, пользовательское представление или частичное представление будут иметь только небольшие различия HTML, помогая минимизировать любой код, специфичный для сайт клиента.

Я надеюсь, что вы следовали этому фону!

Таким образом, одна HTML-страница может состоять из множества небольших фрагментов частичных представлений HTML, которые могут поступать из определенных папок для клиента или из универсальной версии. Я надеюсь облегчить нашему дизайнеру внесение незначительных изменений на страницу, легко видя, где в структуре папок находится тот фрагмент HTML, который он хочет изменить.

Мое предложение состоит в том, что каждый частичный фрагмент будет заключен в скобки с комментариями HTML, такими как:

{Содержимое частичного}

Очевидно, я мог бы вставить их вручную, но это просто проблема, опечатки, скопированные, а затем измененные версии клиента, которые не обновляются с правильным URL-адресом. Думаю, должно быть возможно получить это из какого-то контекста и внедрить.

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

Для меня это предлагает ActionFilter для действия, который я могу применить ко всему сайту, а затем отключить для определенных действий. Я надеюсь, что одно из переопределяемых событий позволит мне установить этот путь, но я не могу найти его где-нибудь. Кроме того, кажется, что OnResultExecuting срабатывает до того, как был выбран Partial, а OnResultExecuted, по-видимому, уже записал содержимое Partial, поэтому я не могу вставить здесь начальный комментарий. Я также не могу найти ссылку на путь к выбранному фрагменту.

Просто для полноты картины я намерен, чтобы этот атрибут писал эти комментарии только при компиляции в режиме отладки.

Итак, кто-нибудь знает, как я могу получить путь к выбранному представлению без какого-либо взлома между FindPartialView и атрибутом? Является ли мой метод атрибутов лучшим выбором или есть более простой способ сделать это? Возможно, что-то уже встроено!

Большое спасибо за вашу помощь.


person Steve Owen    schedule 21.12.2010    source источник


Ответы (1)


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

Я переопределил WebViewPage по умолчанию (я использую движок Razor) и, в частности, ExecutePageHierarchy для ввода комментариев:

public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic>
{
}

public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel>
{
    public bool DisplaySourceCodeComments
    {
        get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; }
        set { ViewBag.__DisplaySourceCodeComments = value; }
    }

    public override void ExecutePageHierarchy()
    {
        base.ExecutePageHierarchy();

        // Filters can be used to set and clear this value so we can decide when to show this comment
        if (!DisplaySourceCodeComments) return;

        var sw = Output as StringWriter;
        if (sw == null) return;

        var sb = sw.GetStringBuilder();
        sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath));
        sb.AppendFormat("<!-- End of {0} -->", VirtualPath);
    }

VirtualPath сообщает нам точный файл, используемый для создания HTML, поэтому мы можем ввести имя файла до и после. На данный момент это ничего не делает, так как по умолчанию не показывать комментарии ("?? false" в DisplaySourceCodeComments).

Также, чтобы использовать эту страницу просмотра, вам нужно отредактировать Views/Web.config и изменить pageBaseType на этот тип.

Я хочу выборочно включать и выключать эти комментарии, поэтому я создал ActionFilter:

public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute
{
    private readonly bool _displaceSourceCodeComments;

    public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments)
    {
        _displaceSourceCodeComments = displaceSourceCodeComments;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var viewResult = filterContext.Result as ViewResultBase;
        if (viewResult == null) return;

        viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments;
    }
}

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

При этом любое действие может включать комментарии к исходному коду с помощью [DisplaySourceCodeComments(true)]

или, очевидно, снова отключить его с помощью false

Атрибут проверяет, что результатом контекста является ViewResultBase, что означает только Views и Partials, поэтому Json или Content или перенаправления не затрагиваются, что тоже очень удобно.

Наконец, я делаю фильтр этого действия глобальным при работе в режиме отладки, чтобы каждое представление и партиал включали исходный комментарий, добавляя следующую строку в global.asax.cs:

[#]если ОТЛАДКА

        // When in debug mode include HTML comments showing where a view or partial has come from
        GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true));

[#]конец

Я очень рад, что наконец разобрался, поэтому надеюсь, что это будет полезно для кого-то еще.

person Steve Owen    schedule 23.09.2011