Reputation: 97
From my understanding, a view model represents only the data that I would like to display in a particular view and can consist of properties from multiple domain models. I also understand that view models act as a data-binder between my domain models and views.
With that said, I have the following model:
public class Image
{
public int ImageID { get; set; }
public string ImageCaption { get; set; }
public int NumOfLikes { get; set; }
public string ImageFilePath { get; set; }
}
And a ProfileViewModels
class with the the following view models:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Splend.Models
{
public class ImageUploadViewModel
{
}
public class EditUserProfileViewModel
{
}
public class ViewUserProfileViewModel
{
}
public class ViewImagesViewModel
{
}
}
Firstly, I assumed that this is the correct way of creating view models based on AccountViewModels
generated by ASP.NET Identity. Secondly, I have not scaffolded any items from these two models. So I have no views or controllers yet.
ImageUploadViewModel
is a view model?Upvotes: 2
Views: 1660
Reputation: 23690
I wouldn't recommend a one-size-fits-all approach to creating and managing view models cause it gets complicated quickly, especially if you come to assign validation to them.
It seems like you're trying to anticipate the view models that you need before you create your views?
Generally I would recommend having a 1:1 relationship between your view models and your views and ensure that your view models contain the least amount of fields to hold only the information that is required to display said view.
I have assumed that you have a users that have multiple Images
and the following view models:
public class ProfileViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
public string FullName { get; set; }
public List<ImageViewModel> UserImages { get; set; }
}
// View model to represent user images
public class ImageViewModel
{
public int ImageID { get; set; }
public string ImageCaption { get; set; }
public int NumOfLikes { get; set; }
public string ImageFilePath { get; set; }
}
Here's how to map to your view model. Simply create a new instance of your view model class(es) , assign the values to them and pass them to the view:
[HttpGet]
public ActionResult EditUser()
{
//
// LOAD INFO ABOUT THE USER (Using a service layer, but you're probably just using Entity Framework)
//
// Get the user ID?
var userId = this.User.Identity.GetUserId();
// Get the user domain models from the database?
var userDomainModel = this.UserService.GetUserInfo(userId);
// Get the user's image domain models from the database?
var userImagesDomainModelList = this.UserImageService.GetImagesForUser(userId);
//
// THE VIEW MODEL MAPPING STARTS HERE...
//
// Create an instance of your view model and assign basic info
var responseModel = ProfileViewModel()
{
public string UserName = userDomainModel.UserName;
public string Password = userDomainModel.Password;
public string FullName = userDomainModel.FullName;
}
// Initialise list for images
responseModel.UserImages = new List<ImageViewModel>();
// Loop though each image domain model and assign them to the main view model
foreach (var imageDomainModel in userImagesDomainModelList)
{
// Initialise image view model
var imageViewModel = new ImageViewModel()
{
ImageID = imageDomainModel.ImageID,
ImageCaption = imageDomainModel.ImageCaption,
NumOfLikes = imageDomainModel.NumOfLikes,
ImageFilePath = imageDomainModel.ImageFilePath
};
// Add the image view model to the main view model
responseModel.UserImages.Add(imageViewModel);
}
// Pass the view model back to the view
return View(responseModel);
}
Just map the incoming values that have been posted to your domain models in the same way:
[HttpPost]
public ActionResult UpdateImage(UpdateImageViewModel requestResponseModel)
{
// Get the user ID?
var userId = this.User.Identity.GetUserId();
// Map incoming view model values to domain model
var imageDomainModel = new Image()
{
ImageID = requestResponseModel.ImageId,
ImageCaption = requestResponseModel.ImageCaption,
NumOfLikes = requestResponseModel.NumOfLikes,
ImageFilePath = requestResponseModel.ImageFilePath,
}
try
{
// Send the domain model up to your service layer ready to be saved
this.UserImageService.UpdateImage(userId, imageDomainModel);
ViewBag.SuccessMessage = "Your image was updated";
}
catch (Exception)
{
// Critical error saving user image
}
return View(requestResponseModel);
}
At no point will you try to attach your View Models
to your Entity Framework context. If you did, then it would reject it. It knows which models it can accept by the IDbSet<object>
properties that are defined within the definition of your DbContext:
public class YourDbContext : DbContext
{
public YourDbContext() : ("YourDbConnectionStringName")
{
}
// Definitions of valid Entity Framework objects
public virtual IDbSet<User> Users { get; set; }
public virtual IDbSet<Image> Images { get; set; }
}
var dbContext = new YourDbContext();
var imageViewModel = new ImageViewModel();
var imageDomainModel = new Image();
// Adding object defined within your db context is fine...
dbContext.Set<Image>().Add(imageDomainModel); // OK
dbContext.Set<Image>().Add(imageViewModel); // Not OK, will result in exception
I personally don't sent Domain Models up to my service layer, I use DTOs (Data Transfer Objects). But that's a whole other story...
Please see this post from me that explains how I lay out my MVC applications: https://stackoverflow.com/a/32890875/894792
Upvotes: 1