Я обнаружил, что пользовательские элементы управления невероятно полезны при работе с веб-форматами 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, но я считаю, что этот подход функционально эквивалентен привязке частичного представления и контроллера вместе при сохранении чистой разметки. Однако должно быть ясно, что разработчику по-прежнему принадлежит только логика, связанная с представлением, в управлении. Логика доступа к данным и доступа к данным все еще принадлежит к их соответствующим уровням.