Подтвердить что ты не робот

ASP.Net MVC3 - Пропускает разметку бритвы как параметр

У меня есть помощник по имени EditableArea который предоставляет пользователю div файл, редактируемый во время выполнения (через JS). Помощник EditableArea проверяет, существует ли в БД редактируемая область (не связанная с Area MVC) с указанным идентификатором, если это так, то она отображает область HTML, в противном случае она отображает разметку по умолчанию, указанную в качестве параметра помощника:

@Html.EditableArea(someId, "<p>Click to edit contents</p>")

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

@using (Html.EditableArea(someId))
{
    <p>Click to edit contents</p>
}

Или что - то подобное, как путь @section работы в MVC3.

Как я могу этого достичь?

Я могу сделать IDisposable который в своем Dispose закрывает TagBuilder и т.д., Но при таком подходе разметка будет по-прежнему отображаться (я могу очистить визуализированное содержимое в Dispose() но блок кода все равно будет запускаться без необходимости, что я ' хотел бы избежать).

И если я не использую using есть ли какой-то другой способ передать блок бритвы помощнику, который может быть на самом деле или не может быть визуализирован?

4b9b3361

Ответ 1

Вот пример, который я использую для рендеринга jQuery Template, передавая в шаблоне Id и синтаксис стиля бритва для самого шаблона:

public static MvcHtmlString jQueryTmpl(this HtmlHelper htmlHelper, 
    string templateId, Func<object, HelperResult> template) 
{
    return MvcHtmlString.Create("<script id=\"" + templateId + 
        "\" type=\"x-jquery-tmpl\">" + template.Invoke(null) + "</script>");
}

и это будет вызвано с помощью

@Html.jQueryTmpl("templateId", @<text>any type of valid razor syntax here</text>)

В основном используйте Func<object, HelperResult> как свой параметр и template.Invoke(null) (с аргументами, если необходимо) для его рендеринга. Очевидно, вы можете пропустить вызов .Invoke(), чтобы избежать рендеринга разметки по умолчанию.

Ответ 2

Просто, чтобы расширить принятый ответ, так как потребовалось некоторое время для решения подобной проблемы, и это вопрос, который возник. Я действительно нуждался в @helper, который принимал бы текст бритвы, поскольку шаблон должен содержать довольно некоторый код. Я долго играл, пытаясь использовать несколько версий типа @helper item(Func<object, HelperResult> input), которые я нашел в Интернете, без успеха. Поэтому я пошел на такой подход, как:

namespace project.MvcHtmlHelpers
{
    public static class HelperExtensions
    {
        public static MvcHtmlString RazorToMvcString(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
        {
            return MvcHtmlString.Create(template.Invoke(null).ToString());
        }
    }
}

и

@project.MvcHtmlHelpers    
@helper item(other input, MvcHtmlString content)
    {
        <div class="item">
            ...other stuff... 
            <div class="content">
                @content
            </div>
        </div>
    }

и используйте это через

@item(other input, @Html.RazorToMvcString(@<text>this is a test</text>))

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

Ответ 3

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

@helper HelperWithChild(Func<object, HelperResult> renderChild)
{
    <div class="wrapper">
        @renderChild(this)
    </div>
}

@HelperWithChild(@<h1>Hello</h1>)

Для многострочной разметки также требуется <text>:

@HelperWithChild(@<text>
    @AnotherHelper()

    <h1>
        With more markup
    </h1>
</text>)

@helper AnotherHelper()
{
    <p>
        Another helper
    </p>
}

Хотя я не уверен, как this отразится на Model - мои помощники используют только их параметры.