Я обнаружил, что пользовательские элементы управления невероятно полезны при работе с веб-форматами ASP.NET. Инкапсулируя код, необходимый для отображения элемента управления с разметкой, создание повторно используемых компонентов было очень простым и очень, очень полезным.
В то время как MVC обеспечивает удобное разделение проблем, это, похоже, нарушает инкапсуляцию (т.е. вы можете добавить элемент управления без добавления или использования его поддерживающего кода, что приведет к ошибкам во время выполнения). При необходимости изменять контроллер каждый раз, когда я добавляю элемент управления в представление, мне кажется, что он интегрирует проблемы, а не их разделять. Я бы предпочел разбить идеологию пуриста MVC, чем отказаться от преимуществ многоразовых, упакованных элементов управления.
Мне нужно включить компоненты, похожие на пользовательские элементы веб-форм, на весь сайт, но не для всего сайта, а не на уровне, который принадлежит главной странице. Эти компоненты должны иметь собственный код не только разметки (для взаимодействия с бизнес-слоем), и было бы замечательно, если бы диспетчер страниц не нуждался в информации об элементе управления. Поскольку пользовательские элементы управления MVC не имеют кода, я не вижу хорошего способа сделать это.
Обновление НАКОНЕЦ, хороший (и, ретроспективный, очевидный) способ достичь этого.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace K.ObjectModel.Controls
{
public class TestControl : ViewUserControl
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.Write("Hello World");
base.Render(writer);
}
}
}
Создайте новый класс, который наследует ViewUserControl
Переопределите метод .Render()
, как показано выше.
Зарегистрируйте элемент управления через связанный с ним ASCX, как и в webForm:
<%@ Register TagName="tn" TagPrefix="k" Src="~/Views/Navigation/LeftBar.ascx"%>
Используйте соответствующий тег на любом видном или главном страницах, который вам нужен:
<k:tn runat="server"/>
Убедитесь, что ваш .ascx наследует ваш новый элемент управления:
<%@ Control Language="C#" Inherits="K.ObjectModel.Controls.TestControl" %>
Войля, ты в движении. Это проверено с помощью ASP.NET MVC 2, VS 2010 и .NET 4.0.
Ваш собственный тег ссылается на частичный вид ascx, который наследуется от класса TestControl. Затем элемент управления переопределяет метод Render()
, который вызывается для визуализации представления, что дает вам полный контроль над процессом из тега для вывода.
Разница между использованием этого подхода и вызовом Html.RenderPartial()
или `Html.RenderAction() 'заключается в добавлении элемента управления в представление выполняется с помощью тега в виде webforms, который не только более удобен для дизайнеров, но и сохраняет их от необходимости знать имена и методы контроллера. Имя класса управления изолировано от ASCX, что также облегчает их удаление в сборке и повторное использование в разных проектах.
Некоторые могут сказать, что это нарушает SoC, но я считаю, что этот подход функционально эквивалентен привязке частичного представления и контроллера вместе при сохранении чистой разметки. Однако должно быть ясно, что разработчику по-прежнему принадлежит только логика, связанная с представлением, в управлении. Логика доступа к данным и доступа к данным все еще принадлежит к их соответствующим уровням.