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

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

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


person Łukasz Sowa    schedule 17.09.2008    source источник
comment
Я написал руководство о том, как мне это удалось: britishdeveloper. co.uk/2010/06/ должно помочь   -  person BritishDeveloper    schedule 22.06.2011


Ответы (9)


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

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

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.

person Generic Error    schedule 14.04.2009
comment
Это метод, рекомендованный Скоттом Гутери, так что я должен согласиться. - person Simon Fox; 22.09.2009
comment
@Simon Fox - есть ссылка на рекомендацию Скоттгу? Не нашел. - person orip; 15.12.2009
comment
weblogs.asp.net/scottgu/archive/2007/12/06/ - person Dan Atkinson; 18.03.2010
comment
Прости. Есть небольшие проблемы с пониманием части этого. Конструктору контроллера передается экземпляр IViewDataFactory, но система ожидает конструктор без параметров. Я также не знаком с синтаксисом C # (в частности, MasterViewData, new ()) для интерфейса. Может кто-нибудь объяснить это или указать мне на хороший ресурс. Спасибо. - person Jason; 12.05.2010
comment
@Jason: Asp.net MVC позволяет указать фабрику контроллеров, что означает, что вы можете использовать структуру внедрения зависимостей для создания экземпляров контроллеров, которые принимают параметры конструктора. where T : MasterViewData, new() сообщает компилятору, что метод Create может быть вызван только для типов, которые расширяют MasterViewData (что IndexViewData делает в этом случае) и которые используют конструктор по умолчанию или конструктор без параметров. Другими словами, я должен уметь сказать MasterViewData data = new T();. - person StriplingWarrior; 16.07.2010
comment
Мне нравится иметь строго типизированные модели для работы, но я не большой поклонник связывания основных данных со всеми моими другими моделями и действиями. Вскочить в эту тему немного поздно, но я опубликовал свой подход к основным данным, который делает вещи более свободными. - person Todd Menier; 10.08.2010
comment
Может ли кто-нибудь помочь мне понять, где / когда значение, присвоенное свойству Navigation? - person IsmailS; 19.03.2011

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

  1. Данные основного представления полностью отделены от «обычных» моделей представления. Это композиция, а не наследование, и в результате получается более слабосвязанная система, которую легче изменить.
  2. Модели главного представления создаются полностью отдельным действием контроллера. «Обычным» действиям не нужно беспокоиться об этом, и нет необходимости в фабрике данных представления, что на мой вкус кажется слишком сложным.
  3. Если вы используете такой инструмент, как AutoMapper, чтобы сопоставить ваш домен с моделями представления, вам будет проще настроить, потому что ваши модели представления будут больше напоминать ваши модели домена, если они не наследуют данные основного представления.
  4. Используя отдельные методы действий для основных данных, вы можете легко применить кэширование вывода к определенным областям страницы. Обычно основные представления содержат данные, которые меняются реже, чем содержимое главной страницы.
person Todd Menier    schedule 09.08.2010
comment
+1. Еще одно преимущество состоит в том, что одно и то же представление может использовать разные главные страницы в зависимости от текущего состояния выполнения. - person StriplingWarrior; 26.10.2010
comment
Мне очень нравится этот ответ - другие изложенные подходы кажутся немного сложными. - person Paddy; 05.01.2011
comment
На мой взгляд, это наиболее элегантное решение. - person autonomatt; 05.01.2011
comment
Мне это решение тоже кажется лучшим. Бесконечно благодарен! - person JimDaniel; 15.01.2011
comment
Для меня это звучит так, как будто в конечном итоге получается главный контроллер, который содержит все действия, используемые Html.RenderAction, который извлекает выгоду из DI и всего остального. Это правда? Есть ли какой-либо риск, позволяя умным пользователям запрашивать одно из этих действий напрямую? Есть способ предотвратить это? - person flipdoubt; 03.03.2012
comment
Это отличный способ, но помните, что вам все равно нужно указать маршруты для ваших частичных действий. См. Этот ответ stackoverflow.com/a/3553617/56621 - person Alex from Jitbit; 05.03.2012
comment
Мы используем MvcContrib и T4MVC, поэтому у нас нет проблем с маршрутизацией. Хороший совет, jitbit. - person flipdoubt; 10.03.2012
comment
Этот подход более естественен - ​​когда у меня была такая же проблема «мастер-ребенок», я пришел к такому же подходу. В этом случае логичнее использовать композицию вместо наследования ... - person ajukraine; 13.12.2012
comment
Согласен с преимуществами, указанными в этом ответе, но, на мой взгляд, есть один недостаток. Он использует RenderAction, который нарушает однозначное поведение, которое я предпочитаю в MVC (1 HTTP-запрос = ›1 маршрут разрешен =› 1 контроллер = ›1 действие =› 0 или 1 получена модель (возможно, включая подмодели) = › Отрендерено 0 или 1 представление (возможно, включая частичные представления с использованием подмоделей, уже загруженных в модель основного представления). Использование RenderAction означает использование множества контроллеров и действий для одного запроса страницы. На мой взгляд, это немного сравнимо с использованием iframe в html. Вот почему я предпочитаю ответ Generic Error. - person Frédéric; 15.05.2013

ИЗМЕНИТЬ

Общая ошибка предоставила лучший ответ ниже. Пожалуйста, прочтите!

Исходный ответ

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

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

person Michael La Voie    schedule 04.06.2009
comment
СПАСИБО! Этот пример ИМЕННО то, что я делаю ... категория на каждой странице, поступающей из базы данных. - person Martin; 03.08.2009
comment
Скотт Гутери, один из авторов MVC, рекомендует решение, предоставленное @Generic Error, ниже. - person Simon Fox; 22.09.2009
comment
+1 за направление к лучшему ответу, даже если ваш официально прав и принят в качестве ответа OP. - person IsmailS; 19.03.2011
comment
+1 за направление к лучшему ответу, даже если ваш официально прав и принят в качестве ответа OP. - person Dave Jellison; 04.08.2011
comment
На самом деле, Todd Menier's на данный момент лучший ответ на этот вопрос. - person andreialecu; 27.09.2011

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

person Ian P    schedule 17.09.2008

Я провел небольшое исследование и наткнулся на эти два сайта. Может, они смогут помочь.

Совет № 31 по ASP.NET MVC - Передача данных на главные страницы и пользовательские элементы управления

Передача данных на главные страницы с помощью ASP.NET MVC

person David Negron    schedule 17.09.2008

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

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

person Matt Mitchell    schedule 17.09.2008

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

person Community    schedule 17.09.2008

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

person dimarzionist    schedule 17.09.2008

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

<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.

person rasx    schedule 30.09.2009
comment
многим это может показаться немного хакерским или «нечистым», но он быстро выполняет свою работу. - person argh; 04.05.2010
comment
Фу. Ваш код кажется намного сложнее поддерживать, чем если бы вы использовали Html.RenderAction (). - person Dan Esparza; 30.09.2010