2012-06-29 6 views
27

Для ViewBag, я слышал, что это было не-не использовать. Я бы предположил, что содержимое ViewBag должно быть включено в модель представления?MVC ViewBag Best Practice

Вопрос:

  1. Является ли мое предположение выше лучшей практики. (Не использовать ViewBag и второй, чтобы иметь его в модели представления)

  2. Есть ли ситуации, когда ViewBag абсолютно необходим?

+7

С точки зрения Microsoft, мы не согласны с тем, чтобы никогда не использовать ViewBag или ViewBag - No No. Использование ViewBag для передачи данных модели - другое дело и должно быть обескуражено. Использование ViewBag для передачи метаданных (Select List) отлично. Pro MVC от Sanderson и других книг используют их и не делают таких окончательных прокламаций - 2. Abs необходимо - я сомневаюсь. – RickAndMSFT

ответ

25

ViewBag - динамический словарь. Поэтому при использовании ViewBag для передачи данных между методами действий и представлениями ваш компилятор не сможет поймать, если вы делаете опечатку в своем коде при попытке получить доступ к элементу ViewBag в своем представлении. Ваше представление будет сбой во время выполнения :(

Как правило, рекомендуется использовать модель представления для передачи данных между вашими методами действий и представлениями. View model - это простой класс POCO, который обладает свойствами, специфичными для представления. если вы хотите передать некоторые дополнительные данные для просмотра, добавьте новое свойство в свою модель просмотра и используйте это. Сильно напечатанные представления делают код более чистым и более простым в обслуживании. При таком подходе вам не нужно делать явное литье ваш viewbag элемент словаря для некоторых типов назад и вперед, которые вы должны сделать с видом сумки.

public class ProductsForCategoryVm 
{ 
    public string CategoryName { set;get; } 
    public List<ProductVm> Products { set;get;}  
} 
public class ProductVm 
{ 
    public int Id {set;get;} 
    public string Name { set;get;} 
} 

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

public ActionResult Category(int id) 
{ 
    var vm= new ProductsForCategoryVm(); 
    vm.CategoryName = "Books"; 
    vm.Products= new List<ProductVm> { 
    new ProductVm { Id=1, Name="The Pragmatic Programmer" }, 
    new ProductVm { Id=2, Name="Clean Code" } 
    } 
    return View(vm); 
} 

И ваша точка зрения, которая сильно типизированных к модели представления,

@model ProductsForCategoryVm 
<h2>@Model.CategoryName</h2> 
@foreach(var item in Model.Products) 
{ 
    <p>@item.Name</p> 
} 

DropDown данные?

Много учебников/книг содержит образцы кода, которые используют ViewBag для выпадающих данных. Я лично все еще чувствую, что ViewBag не следует использовать для этого. Он должен быть свойством типа List<SelectListItem> в вашей модели просмотра, чтобы передать выпадающие данные. Вот post с примером кода о том, как это сделать.

Существуют ли ситуации, когда ViewBag абсолютно необходим?

Есть некоторые действительные случаи использования, где вы можете (не нужно) использовать ViewBag для передачи данных. Например, вы хотите отобразить что-то на странице Layout, для этого вы можете использовать ViewBag. Другим примером является ViewBag.Title(для заголовка страницы), присутствующего в шаблоне MVC по умолчанию.

public ActionResult Create() 
{ 
    ViewBag.AnnouncementForEditors="Be careful"; 
    return View(); 
} 

И в макете, вы можете прочитать ViewBag.AnnouncementForEditors

<body> 
<h1>@ViewBag.AnnouncementForEditors</h1> 
<div class="container body-content"> 
    @RenderBody() 
</div> 
</body> 
+0

Модель хранится в ViewBag, так что это всегда необходимо иметь. Использование магической строки не может быть пиком ремонтопригодности, но в отличие от использования модели, она обеспечивает соблюдение соглашения об объявлении типа и переменной страницы. –

0
  1. No. Использование ViewModels.
  2. Нет. Если вы создадите идеальный ViewModel, вам никогда не понадобится ViewBag.
4

1) Является ли мое предположение выше лучшей практики. (Не использовать ViewBag и секунд, чтобы иметь его в модели просмотра)

Да.

2) Существуют ли ситуации, когда ViewBag абсолютно необходим?

Нет. Все, что вы сохранили в ViewBag, может войти в модель представления, переданную в представление.

+0

Как насчет метаданных? Должны ли мы вытащить @ ViewBag.Title из шаблонов? – RickAndMSFT

+7

Yeap, выбросьте его. Пожалуйста. Я не хочу видеть в ASP.NET MVC 4. Это заставляет меня хотеть рвать. Используйте его внутри структуры, если вы отметите его как «внутреннее», чтобы разработчик никогда не сталкивался с этим. –

4

Вопрос с ViewBags и рекомендуемое лучшая практика сводится к компиляции проверки времени. ViewBags - это просто словари, и с ними вы получаете «магические» строки, поэтому, если вы в конечном итоге измените тип объекта одного из элементов представления или имя ключа, которое вы не узнаете до времени исполнения, даже если предварительно прекомпилировать представления с помощью <MvcBuildViews>true</MvcBuildViews>.

Лучше всего смотреть модели, даже если вам нужно изменить их, чтобы они соответствовали конкретному виду времени и времени.

26

1) Является ли мое предположение выше лучшей практики. (Не использовать ViewBag и секунды, чтобы иметь его в модели представления)

Вы должны использовать ViewModels вместо передачи данных через ViewBag как можно больше.

2) Существуют ли ситуации, когда ViewBag абсолютно необходим?

Нет никакой ситуации, когда ViewBag абсолютно необходим. Однако есть некоторые данные, которые я лично предпочитаю использовать ViewBag вместо View Model. Например, когда мне нужно заполнить раскрывающийся список для предопределенных значений (например, Города), я использую ViewBag для переноса массива SelectListItem для просмотра. Я предпочитаю не загрязнять мои ViewModels этими данными.

+4

Отличный отклик в соответствии с нашим (MS) опубликованным руководством. Я бы только изменил его от передачи данных к передаче данных модели (метаданные исключены) См. Нижнюю часть моего учебного пособия http://www.asp.net/mvc/tutorials/javascript/working-with-the-dropdownlist-box-and -jquery/examining-how-aspnet-mvc-scaffolds-the-dropdownlist-helper – RickAndMSFT

+0

@RickAndMSFT, я должен администратор, я использовал ваше сообщение, когда впервые узнал ViewBags. Отличный пост, кстати. – SadullahCeran

+1

Хороший ответ, я также думаю, что использование ViewBag вместо загрязнения среды просмотра со списком параметров, которые нужно передать в представление, является хорошей практикой. Если список передан в ViewModel, это потому, что список, вероятно, будет отредактирован или потому, что он «имеет смысл» для модели. Но в случае списка вариантов, где будет выбран только один, ViewBag кажется более чистым. – iberodev

2

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

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

Что касается проблемы магических струн, существует множество решений. Константы, методы расширения и т. Д.

С учетом сказанного, если у вас есть что-то, что отображается на вашей странице, что зависит от контекста страницы, ViewModel - ваш друг.

Erick

+0

Я знаю, что это старо, но не было бы лучше использовать частичное для списка заданий и @ {Html.RenderAction ("SomeAction", "SomeController");} из представления? – wingyip

1

Если вы не можете редизайн ДЕЙСТВУЮЩЕГО ViewModel использовать ViewBag.

0

2. Существуют ли ситуации, когда ViewBag абсолютно необходим?

В некоторых случаях вам необходимо предоставить свои данные от контроллера по макетам, представлениям и частичным представлениям. В этом случае ViewBag очень полезен, и я сомневаюсь, что есть лучший способ.

0

Если бы для этого не было вариантов использования, оно не было бы реализовано в первую очередь. Да, вы можете делать все с помощью ViewModels, но что, если вам это действительно не нужно? Одним из таких сценариев является редактирование объектов. Вы можете напрямую передавать DTO в качестве модели.

@model CategoryDto 
<div class="md-form form-sm"> 
    <input asp-for="Name" class="form-control"> 
    <label asp-for="Name">("Category Name")</label> 
</div> 

Но что, если вы хотите выбрать родительскую категорию категории? Entity DTO идеально держит только свои собственные значения, поэтому для заполнения списка выбора используется ViewBag

<select asp-for="ParentId" asp-items="ViewBag.ParentList"> 
    <option value="">None</option> 
</select> 

Почему это? Хорошо, если у вас есть 50 типов сущностей, каждый из которых имеет какой-то выбор из разных значений, вы просто избегаете создания 50 дополнительных ViewModels.