Question

I've read many articles which they state that querying should not be placed in the Controller, but I can't seem to see where else I would place it.

My Current Code:

public class AddUserViewModel 
{        
    public UserRoleType UserRoleType { get; set; }
    public IEnumerable<SelectListItem> UserRoleTypes { get; set; }

}

public ActionResult AddUser()
    {
        AddUserViewModel model = new AddUserViewModel()
        {

            UserRoleTypes = db.UserRoleTypes.Select(userRoleType => new SelectListItem
            {
                Value = SqlFunctions.StringConvert((double)userRoleType.UserRoleTypeID).Trim(),
                Text = userRoleType.UserRoleTypeName
            })
        };
        return View(model);  
    }

The View:

<li>@Html.Label("User Role")@Html.DropDownListFor(x => Model.UserRoleType.UserRoleTypeID, Model.UserRoleTypes)</li>

How do I retain the View Model and Query and exclude the User Type that should not show up?

Was it helpful?

Solution

I think that you are doing it just fine.

Any way... all you can do to remove the querying logic from controller is having a ServiceLayer where you do the query and return the result.

The MVC pattern here is used correctly... what your are lacking is the other 2 layers (BusinessLayer and DataAccessLayer)... since ASP.NET MVC is the UI Layer.

UPDATE, due to comment:

Using var userroletypes = db.UserRoleTypes.Where(u=> u.UserRoleType != 1); is OK, it will return a list of UserRoleType that satisfy the query.

Then, just create a new SelectList object using the userroletypes collection... and asign it to the corresponding viewmodel property. Then pass that ViewModel to the View.

BTW, I never used the db.XXXX.Select() method before, not really sure what it does... I always use Where clause.

SECOND UPDATE: A DropDownList is loaded from a SelectList that is a collection of SelectItems. So you need to convert the collection resulting of your query to a SelectList object.

var userroletypes = new SelectList(db.UserRoleTypes.Where(u=> u.UserRoleType != 1), "idRoleType", "Name");

then you create your ViewModel

var addUserVM = new AddUserViewModel();
addUserVM.UserRoleTypes = userroletypes;

and pass addUserVM to your view:

return View(addUserVM ); 

Note: I'm assuming your ViewModel has a property of type SelectList... but yours is public IEnumerable<SelectListItem> UserRoleTypes { get; set; } so you could change it or adapt my answer.

OTHER TIPS

I don't see anything wrong with your code other than this db instance that I suppose is some concrete EF context that you have hardcoded in the controller making it impossible to unit test in isolation. Your controller action does exactly what a common GET controller action does:

  1. query the DAL to fetch a domain model
  2. map the domain model to a view model
  3. pass the view model to the view

A further improvement would be to get rid of the UserRoleType domain model type from your view model making it a real view model:

public class AddUserViewModel 
{
    [DisplayName("User Role")]
    public string UserRoleTypeId { get; set; }

    public IEnumerable<SelectListItem> UserRoleTypes { get; set; }
}

and then:

public ActionResult AddUser()
{
    var model = new AddUserViewModel()
    {
        UserRoleTypes = db.UserRoleTypes.Select(userRoleType => new SelectListItem
        {
            Value = SqlFunctions.StringConvert((double)userRoleType.UserRoleTypeID).Trim(),
            Text = userRoleType.UserRoleTypeName
        })
    };
    return View(model);  
}

and in the view:

@model AddUserViewModel 
<li>
    @Html.LabelFor(x => x.UserRoleTypeId)
    @Html.DropDownListFor(x => x.UserRoleTypeId, Model.UserRoleTypes)
</li>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top