0

I wonder what should I use when to fill SelectList on View. I know two ways to do that. First; Set ViewBag on controller's get method.

    ViewBag.DepartmentList = new SelectList(_departmentService.GetAll(), "Id", "Name", selectedValue: user.DepartmentId);

and then use it on view like (you can also do it with ViewData)

    @Html.DropDownListFor(model => model.DepartmentId, (IEnumerable<SelectListItem>)ViewBag.DepartmentList )

Second way that I know is calling service method from view directly:

    @Html.DropDownListFor(model=>model.DepartmentId,new SelectList((new DepartmentService()).GetAll(),"Id","Name", selectedValue: Model.DepartmentId ))

So, sometimes we should return to view passing model to method on the controller post method especially there is an error or ModelState is not valid. As you know, when doing this ViewBag.DepartmentList should be filled on post method, again. On the other hand using second way, there is no need to create and fill ViewBag.DepartmentList either get and post method. But I wonder if there is any difference or which one should i use? Why?

Engineert
  • 192
  • 1
  • 1
  • 16
  • 2
    both are not recommended, you should have a property for it in your ViewModel – Ehsan Sajjad Jan 14 '16 at 12:49
  • Is there any reason about that ? – Engineert Jan 14 '16 at 12:55
  • 2
    it is against the MVC pattern, to query your data source in view, View's responsibility is to just render the html, do the fetching stuff in controller, your view should be just doing logic of rendering html – Ehsan Sajjad Jan 14 '16 at 12:59
  • Sure there is a reason. ViewBag is kind of a messy dynamic object while ViewModel is nicely defined object wich holds all the data your View needs. You mentioned TempData as well - those serve a completely different purpose and they are used to pass data between two requests, not between Controller and View. And the other option, calling a service from a View is an antipattern. Do not even think about it :). – Anton Jan 14 '16 at 13:01
  • ViewBag may hold small bits of data that are not related to a particular view. Let's say, hmm, an MVC filter (rather than a controller) needs to store some general data that may or may not be used by one of the views or partial views on the page. No specific example hitting my mind at the very moment, however if you read some of the tutorials from Microsoft you will realize they use the ViewBag for example to store the page title. – Anton Jan 14 '16 at 13:45

2 Answers2

2

neither of those two options is a good way to go. Consider using a ViewModel instead.

Anton
  • 2,458
  • 2
  • 18
  • 30
  • What is the advantage of using property in Model instead of call service method directly ? I am serializing my model object to store for a while. If I bind this new property before post method calling, there will be extra data and i should clear it. If I dont bind it before posting, then I should fill this property before returning view when there is an error or modelState.IsValid is false. I dont want to effort to manage it if there is not a big reason that i musnt use it. – Engineert Jan 14 '16 at 13:07
  • I am sorry, I guess I do not understand what are you trying to achieve - why would you serialize your ViewModel at all? Never mind, please consider that a View should be completely agnostic to the business logic implemented by the service layer. View is just a dummy presentation mechanism which grabs data served by a Controller through a ViewModel and displays the data. It is the basic of the MVC architecture and my strong recommendation is that following the architecture is itself a very good reason to go the right way. – Anton Jan 14 '16 at 13:19
  • @Engineert you have should have a Data Model mapped to ViewModel, ViewModel is for views and Model is your data model aks DTO – Ehsan Sajjad Jan 14 '16 at 13:24
  • Ok I got it. Thanks. – Engineert Jan 14 '16 at 13:32
0

As said, use a view model to hold the select list values

--DepartmentViewModel

 [Required]
 public int DepartmentId { get; set; }
 public IEnumerable<SelectListItem> DepartmentSelectList { get; set; }

--DepartmentController

 var vm = new DepartmentViewModel();
 vm.DepartmentSelectList = new DepartmentService().GetAll().Select(c => new SelectListItem
        {
            Text = c.DepartmentName,
            Value = c.Id.ToString()
        }).ToList();

--View

 @Html.DropDownListFor(model => model.DepartmentId, model.DepartmentSelectList)
Kevin
  • 13
  • 3
  • Strongly typed Views make the code cleaner and more easy to maintain. You don't need to do explicit Casting back and forth. – Kevin Jan 14 '16 at 13:08