Is it good to define properties of “Model” type in

2019-07-19 05:35发布

问题:

I've read couple of posts on using ViewModel in ASP.net MVC and realized it is different from "ViewModel" in M-V-VM pattern.

ViewModel are used in order to avoid having Model being accessed directly from View but is it good approach to have properties of type (defined at Model layer) in ViewModel? Which means eventually we need to include Model namespace to ViewModel.

E.g.

Model
1. YesNoTBDValue entity/POCO class

public partial class YesNoTBDValue
{
    public int Id { get; set; }
    public string Name { get; set; }
}

2 YesNoTBDValue class used in Project entity (defined in Model itself)

public partial class Project
{
     public virtual YesNoTBDValue IsAvailable { get; set; }
}

View Model
1. ProjectEditViewModel

public class ProjectEditViewModel
{
HERE TO INCLUDE YesNoTBDValue CLASS, I NEED TO INCLUDE MODELS 
OR THERE IS BETTER WAY?
    public List<YesNoTBDValue> YesNoTBDValues { get; set; }
    public int IsAvailableSelectedItemId { get; set; }
}

Controller
Project Controller (in edit action creating new instance of view model)

ProjectEditViewModel projectEditViewModel = new ProjectEditViewModel
{
    YesNoTBDValues = db.YesNoTBDValues.ToList()
};

View
Showing DropDownList from YesNoTBDValues list and keeping selected item in IsAvailableSelectedItemId

@Html.DropDownList("IsAvailableSelectedItemId ", 
new SelectList(Model.YesNoTBDValues, "Id", "Name",
            Model.IsAvailableSelectedItemId ))

Please suggest me how it should be properly coded.

Repeating question: Should ViewModel include Model's namespace? In my example YesNoTBDValue is defined in Model and to use it I am using Model's namespace

/ ANOTHER APPROACH /

Not satisfied with my existing approach, I downloaded the Microsoft Nuget Gallery source code from github and realize that they have never used MODELS inside VIEWMODEL which makes sense to me. I changed above code a little bit (in order to remove reference of Model from ViewModel) and found it working great.

Here are my changes:

Model No Changes, Same as it is

View Model
1. Create Replica of YesNoTBDValue class say YesNoTBDValueViewModel

public class YesNoTBDValueViewModel
{
   public int Id { get; set; }
   public string Name { get; set; }
}

2 Use this ViewModel in ProjectEditViewModel and remove Model reference

public class ProjectEditViewModel
{
     public List<YesNoTBDValueViewModel> YesNoTBDValues {get;set;}
     public int IsAvailableSelectedItem {get;set;}
}

Controller Change in way of populating these values. (In Edit action)

ProjectEditViewModel projectEditViewModel = new ProjectEditViewModel
{
    YesNoTBDValues = db.YesNoTBDValues.Select(
                x => new LMSPriorTool.ViewModels.YesNoTBDValueVM
 {
    Id = x.Id,
    Name = x.Name
 }).ToList()
}

And found after these changes, it is working fine too. I like this second approach as in this Models and ViewModels are totally separated from each other. Keeping this question open for further discussion.

Please throw some light if I'm missing something here.

回答1:

I try to keep the ViewModel containing only simple types which are natural in the context of the view. That way I keep rendering logic in the view to a minimum and keep the view clean.

Your ViewModel can be represented very simply with something like:

public class ProjectEditViewModel
{
    public int YesNoTBDValueSelected { get; set; }
    public SelectList YesNoTBDValueOptions { get; set; }
}

or

public class ProjectEditViewModel
{
    public int YesNoTBDValueSelected { get; set; }
    public IEnumerable<SelectListItem> YesNoTBDValueOptions { get; set; }
}

Now logic for generating SelectList goes in your Project <-> ProjectEditViewModel mapping and is kept out of View.