Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

ASP.NET MVC свой HtmlHelper + Partial

#c_sharp #aspnet #aspnet_mvc #mvc


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

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

@RenderBody
У нас есть IDENT (идентификатор) и какое-то тело. Чтобы далее в какой-либо другой View вызывать нечто подобное: @using(Html.DrawMyCustomSection("ident12345")) { Передать в тело } Чтобы на выходе иметь:
Передать в тело
Вопрос в самой "элегантности" решения. Самый простой способ - отказаться от Partial View вообще и рендерить всё средствами MvcHtmlString. Но это, сдаётся мне, моветон и я его не рассматриваю, как достойный вариант. Второй способ - использовать кастомный хелпер с реализацией IDisposable и рендерингом PartialView с заменой контрольных строк {IDENT} и {BODY} на своё. Этот вариант вроде как лучше, но ненамного :) Третий способ - строготипизированная модель для PartialView, в которой всё передавать. Хороший способ, как по мне. Но не могу понять как правильно передать само тело в PartialView и как там его разворачивать. Также можно накрутить реализации с ViewBag / ViewData, но это совсем плохо. Отсюда вопрос: Как правильно, грамотно и красиво передать в PartialView параметры и отрендерить тело в основное представление? Использовать строготипизированную модель, тогда как в неё записать (получить) то, что было в основной вьюшке указано в теле? Буду рад любому ответу и\или примеру. Спасибо!


Ответы

Ответ 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 (если еще не добавлено): ... ... Вызов будет выглядеть, например, так @using (Html.UserIdentity("ident12345")) {

Hello ident12345!

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

Hello ident12345!

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

Ответ 2



Мне кажется именно для подобных целей и был создан View Component Создаем класс с названием нового компонента [ViewComponent] public class ShowIdent { public string Invoke(string idParam, string textParam) { return $"
{textParam}
"; } } Вызываем в нужной вьюхе @await Component.InvokeAsync("ShowIdent", new { idParam = "ident12345", textParam = "Передать в тело"}) Более подробно о View Component тут: https://metanit.com/sharp/aspnet5/7.6.php

Комментариев нет:

Отправить комментарий