ASP.NET MVC свой HtmlHelper + Partial

377
09 декабря 2016, 08:57

Доброго дня, друзья! Тщательно готовился перед тем как задать вопрос. И вот.

Задача такая - есть часто повторяемый код вёрстки (сам код специально упрощён, на деле там много всего из-за чего и встал, собственно, вопрос более грамотной реализации). Хочется сделать подобный Partial View:

<div id="{IDENT}">
@RenderBody
</div>

У нас есть IDENT (идентификатор) и какое-то тело. Чтобы далее в какой-либо другой View вызывать нечто подобное:

@using(Html.DrawMyCustomSection("ident12345"))
{
<b>Передать в тело</b>
}

Чтобы на выходе иметь:

<div id="ident12345">
<b>Передать в тело</b>
</div>

Вопрос в самой "элегантности" решения. Самый простой способ - отказаться от Partial View вообще и рендерить всё средствами MvcHtmlString. Но это, сдаётся мне, моветон и я его не рассматриваю, как достойный вариант.

Второй способ - использовать кастомный хелпер с реализацией IDisposable и рендерингом PartialView с заменой контрольных строк {IDENT} и {BODY} на своё. Этот вариант вроде как лучше, но ненамного :)

Третий способ - строготипизированная модель для PartialView, в которой всё передавать. Хороший способ, как по мне. Но не могу понять как правильно передать само тело в PartialView и как там его разворачивать.

Также можно накрутить реализации с ViewBag / ViewData, но это совсем плохо.

Отсюда вопрос: Как правильно, грамотно и красиво передать в PartialView параметры и отрендерить тело в основное представление? Использовать строготипизированную модель, тогда как в неё записать (получить) то, что было в основной вьюшке указано в теле?

Буду рад любому ответу и\или примеру. Спасибо!

Answer 1

Насколько я понял, вам требуется создать аналог @using(Html.BegibForm()). Т.о. будет возможность оборачивать в div с заданным id другую razor разметку.

Для этого потребуется создать класс или добавить в существующий новый html helper (зависит от того как вы их храните).

Далее пример для отдельного класса:

using System;
using System.IO;
using System.Web.Mvc;
namespace MyWebApplication.Helpers
{
    public static class UserIdentityHelper
    {
        private const string TagName = "div";
        private class UserIdentityContainer : IDisposable
        {
            private readonly TextWriter _writer;
            public UserIdentityContainer(TextWriter writer)
            {
                _writer = writer;
            }
            public void Dispose()
            {
                var builder = new TagBuilder(TagName);
                _writer.WriteLine(builder.ToString(TagRenderMode.EndTag));
            }
        }
        public static IDisposable UserIdentity(this HtmlHelper htmlHelper, string userIdentifier)
        {
            var builder = new TagBuilder(TagName);
            builder.Attributes.Add("id", userIdentifier);
            var writer = htmlHelper.ViewContext.Writer;
            writer.WriteLine(builder.ToString(TagRenderMode.StartTag));
            return new UserIdentityContainer(writer);
        }
    }
}

Не забудьте добавить в web.config новый namespace (если еще не добавлено):

<namespaces>
  ...
  <add namespace="MyWebApplication.Helpers" />
  ...
</namespaces>

Вызов будет выглядеть, например, так

@using (Html.UserIdentity("ident12345"))
{
    <h1>Hello ident12345!</h1>
}

И в результате будет получена разметка следующего вида:

<div id="ident12345">
    <h1>Hello ident12345!</h1>
</div>

Обратите внимание, что вызов UserIdentity возвращает класс, который реализует IDisposable, а закрывающий тэг создается с параметром TagRenderMode.EndTag

READ ALSO
Бегущая строка в абзаце

Бегущая строка в абзаце

Помогите встроить бегущую строку в этот вот абзац

274
Кликнуть по ссылке в Webbrowser

Кликнуть по ссылке в Webbrowser

Загруженная страница содержит ссылки вида:

342
Оптимизация кода c# с большими числами (long)

Оптимизация кода c# с большими числами (long)

Задача следующая: пользователью дают последовательность чисел от 1 до n, мы проверяем может ли произведение двух чисел из последовательности...

265
Windows Phone Application Deployment error

Windows Phone Application Deployment error

Я создал Universal Windows ApplciationСоздаю пакет через Create App Packages

498