Search code examples
c#asp.net-mvcasp.net-mvc-viewmodel

ASP.Net MVC - doing MVVM correctly


I just have a quick question with regards to the MVVM design pattern... I'm just wondering if the way im doing things is the "correct" way?

I have a category mode like so:

[Table("Category")]
public class CategoryModel
{
    [Key]
    public Int32 CategoryId { get; set; }
    public string CategoryName { get; set; }
    public Int32? Category_ParentID { get; set; }
    public virtual CategoryModel Parent_Category { get; set; }
    public virtual ICollection<CategoryModel> SubCategories { get; set; }
    public Int16 CategoryOrder { get; set; }
    public bool Deleted { get; set; }

}

Not all of these are need on the "Create New Category" form, so I've created a ViewModel with just the required fields:

public class CategoryViewModel
{
    public string CategoryName { get; set; }           
    public Int32? Category_ParentID { get; set; }       
}

When a new category is being created, I send in the ViewModel as a parement, and create a new CategoryModel using the values from the ViewModel, like so:

if (ModelState.IsValid)
{

    CategoryModel newCategory = new CategoryModel()
    {
    CategoryName = model.CategoryName,
    Category_ParentID = model.Category_ParentID
    };

    //get the root node, and include it's subcategories
    var categoryList = DatabaseContext.Categories.Include("SubCategories").Single(c => c.CategoryId == model.Category_ParentID);

    //set the order of the category by getting the number of subcategories
    if (categoryList.SubCategories.Count > 0)
    newCategory.CategoryOrder = (Int16)(categoryList.SubCategories.Where(c => !c.Deleted).Max(c => c.CategoryOrder) + 1);
    else
    newCategory.CategoryOrder = 1;

    //save the new category
    DatabaseContext.Categories.Add(newCategory);
    await DatabaseContext.SaveChangesAsync();

    return PartialView("_CategoryModelItem", model);

} else {
    return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}

Is this the right way to do the MVVM design pattern (i.e. the values are taken from a ViewModel, a new Model is created - takes values from the ViewModel - and gets written to the DB)? or am I misunderstanding how its suppored to be done?

Also

How does the "viewing" part work? What I mean is, if I'm listing a category and all of its subcategories in the Index() method of the Controller... should I used a model or viewmodel to display them? Of so, I'll need to add need to add the ICollection to the ViewModel, and then should I grab the data using Entity Framework and the Model class, and then somehow feed that into a ViewModel?


Solution

  • Your are correct but i have some other tips for you:

    • do not name Entity Framework entities with Model postfix, use the names of your DB tables in singular form
    • always return a object. If you want to return a list of objects then wrap this list into a class. It will help you to keep your ViewModels more flexible and easy to extend. Use the wrapper class also if you want to return a single value. I call these objects PageModels.

    If i want to return a single category then my edit page model will look like:

    public class CategoryEditPageModel
    {    
        CategoryModel Category { get; set;}
        //other data not directly related to category itself but needs to be visible on the page
        User CategoryOwner { get; set; }
    }
    

    Then POST only the CategoryModel if you want to update a category.