Передача данных на главную страницу в ASP.NET MVC

102

Как вы можете передавать данные на главную страницу (используя ASP.NET MVC) без нарушения правил MVC?

Лично я предпочитаю кодировать абстрактный контроллер (базовый контроллер) или базовый класс, который передается во все представления.

Лукаш Сова
источник
1
Я написал руководство о том, как мне это удалось: britishdeveloper.co.uk/2010/06/… должно помочь
BritishDeveloper

Ответы:

77

Если вы предпочитаете, чтобы ваши представления имели строго типизированные классы данных представления, это может сработать для вас. Другие решения, наверное, более правильные, но это хороший баланс между дизайном и практичностью ИМХО.

Главная страница принимает строго типизированный класс данных представления, содержащий только относящуюся к нему информацию:

public class MasterViewData
{
    public ICollection<string> Navigation { get; set; }
}

Каждое представление, использующее эту главную страницу, принимает строго типизированный класс данных представления, содержащий его информацию и производный от данных представления главных страниц:

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
}

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

public interface IViewDataFactory
{
    T Create<T>()
        where T : MasterViewData, new()
}

public class ProductController : Controller
{
    public ProductController(IViewDataFactory viewDataFactory)
    ...

    public ActionResult Index()
    {
        var viewData = viewDataFactory.Create<ProductViewData>();

        viewData.Name = "My product";
        viewData.Price = 9.95;

        return View("Index", viewData);
    }
}

Наследование соответствует мастеру, чтобы хорошо просматривать отношения, но когда дело доходит до рендеринга партиалов / пользовательских элементов управления, я объединяю их данные просмотра в данные просмотра страниц, например

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
    public SubViewData SubViewData { get; set; }
}

<% Html.RenderPartial("Sub", Model.SubViewData); %>

Это только пример кода и не предназначен для компиляции как есть. Разработан для ASP.Net MVC 1.0.

Общая ошибка
источник
4
Это метод, рекомендованный Скоттом Гутери, так что я должен согласиться.
Саймон Фокс
@Simon Fox - есть ссылка на рекомендацию Скоттгу? Не нашел.
orip
Сожалею. Есть небольшие проблемы с пониманием части этого. Конструктору контроллера передается экземпляр IViewDataFactory, но система ожидает конструктор без параметров. Я также не знаком с синтаксисом C # (в частности, «MasterViewData, new ()») для интерфейса. Может кто-нибудь объяснить это или указать мне на хороший ресурс. Спасибо.
Джейсон
5
Мне нравится иметь строго типизированные модели для работы, но я не большой поклонник связывания основных данных со всеми моими другими моделями и действиями. Вступить в эту тему немного поздно, но я опубликовал свой подход к основным данным, который делает вещи более свободными.
Тодд Менье,
59

Я предпочитаю разбивать управляемые данными части главного представления на части и визуализировать их с помощью Html.RenderAction . У этого есть несколько явных преимуществ по сравнению с популярным подходом наследования модели представления:

  1. Данные основного представления полностью отделены от «обычных» моделей представления. Это композиция, а не наследование, и в результате получается более слабосвязанная система, которую легче изменить.
  2. Модели главного представления создаются полностью отдельным действием контроллера. «Обычным» действиям не нужно беспокоиться об этом, и нет необходимости в фабрике данных представления, которая кажется мне чересчур сложной.
  3. Если вам случится использовать такой инструмент, как AutoMapper, для сопоставления своего домена с моделями представления, вам будет проще настроить, потому что ваши модели представления будут больше напоминать ваши модели домена, если они не наследуют данные основного представления.
  4. С помощью отдельных методов действий для основных данных вы можете легко применить кэширование вывода к определенным областям страницы. Обычно основные представления содержат данные, которые меняются реже, чем содержимое главной страницы.
Тодд Менье
источник
3
+1. Еще одно преимущество состоит в том, что одно и то же представление может использовать разные главные страницы в зависимости от текущего состояния выполнения.
StriplingWarrior
1
Мне очень нравится этот ответ - другие изложенные подходы кажутся слишком сложными.
Paddy
2
На мой взгляд, это самое элегантное решение.
autonomatt
1
Мне это решение тоже кажется лучшим. Бесконечно благодарен!
JimDaniel
1
Это отличный способ, но помните, что вам все равно нужно указать маршруты для своих «частичных действий». См. Этот ответ stackoverflow.com/a/3553617/56621
Alex
20

РЕДАКТИРОВАТЬ

Generic Error предоставил лучший ответ ниже. Пожалуйста, прочтите!

Оригинальный ответ

Microsoft фактически опубликовала запись об «официальном» способе решения этой проблемы. Это дает пошаговое руководство с объяснением их аргументов.

Короче говоря, они рекомендуют использовать абстрактный класс контроллера, но убедитесь сами.

Майкл Ла Вуа
источник
СПАСИБО! Этот пример ИМЕННО то, что я делаю ... категория на каждой странице, поступающей из базы данных.
Мартин
Скотт Гутери, один из авторов MVC, рекомендует решение, предоставленное @Generic Error, ниже
Саймон Фокс
1
+1 за направление к лучшему ответу, даже если ваш официально прав и принят в качестве ответа OP.
IsmailS
+1 за направление к лучшему ответу, даже если ваш официально прав и принят в качестве ответа OP.
Дэйв Джеллисон
На самом деле, Todd Menier's на данный момент лучший ответ на этот вопрос.
andreialecu
7

Абстрактные контроллеры - хорошая идея, и я не нашел лучшего способа. Мне также интересно посмотреть, что сделали другие люди.

Ян П
источник
2

Я считаю, что общий родительский элемент для всех объектов модели, которые вы передаете в представление, исключительно полезен.

В любом случае между страницами всегда будут иметься некоторые общие свойства модели.

Мэтт Митчелл
источник
0

Объект Request.Params является изменяемым. Довольно просто добавить к нему скалярные значения как часть цикла обработки запроса. С точки зрения представления, эта информация могла быть предоставлена ​​в QueryString или FORM POST. hth


источник
0

Я считаю, что еще одним хорошим способом может быть создание интерфейса для просмотра с некоторым свойством, таким как ParentView некоторого интерфейса, поэтому вы можете использовать его как для элементов управления, которым нужна ссылка на страницу (родительский элемент управления), так и для основных представлений, к которым следует обращаться из Просмотры.

димарзионист
источник
0

Другим решениям не хватает элегантности и они требуют слишком много времени. Прошу прощения за то, что сделал это очень печальное и убогое дело почти год спустя:

<script runat="server" type="text/C#">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        MasterModel = SiteMasterViewData.Get(this.Context);
    }

    protected SiteMasterViewData MasterModel;
</script>

Итак, ясно, что у меня есть статический метод Get () для SiteMasterViewData, который возвращает SiteMasterViewData.

rasx
источник
Для многих это может показаться немного Hacky или «нечистым» , но он получает работу Preety быстро
Argh
Тьфу. Ваш код кажется намного сложнее поддерживать, чем если бы вы использовали Html.RenderAction ().
Дэн Эспарза,