I come from a MVVM in WPF background moving towards ASP.NET MVC. I have a model that is composed of another model called Message, like so:
public class User
{
public int Id { get; set; }
[Required]
[Display(Name = "Register Date")]
public DateTime RegisterDate { get; set; }
[Required]
[StringLength(100)]
public string Username { get; set; } = string.Empty;
[Required]
public Role Role { get; set; }
public List<Message> Messages { get; set; } = new();
}
I am looking to display the latest message on the index page. If this was WPF, I would create a view model to expose this as a new attribute to interface with the view. In MVC, this could be incorporated into the controller as such:
public async Task<IActionResult> Index()
{
var users = await _context.Users
.Include(u => u.Messages)
.ToListAsync();
var vm = users.Select(u => new UserListViewModel
{
Id = u.Id,
RegisterDate = u.RegisterDate,
Username = u.Username,
Role = u.Role,
LatestMessage = u.Messages?.OrderByDescending(m => m.Timestamp)
.FirstOrDefault()?.Content ?? string.Empty
});
return View(vm);
}
Alternatively, this could be incorporated on the model itself with the [NotMapped] annotation. However, this seems incorrect coming from WPF MVVM, since the LatestMessage field is only used for the view, and violates the separation of concerns that I am used to:
public class User
{
public int Id { get; set; }
[Required]
[Display(Name = "Register Date")]
public DateTime RegisterDate { get; set; }
[Required]
[StringLength(100)]
public string Username { get; set; } = string.Empty;
[Required]
public Role Role { get; set; }
public List<Message> Messages { get; set; } = new();
[NotMapped]
public string LatestMessage =>
Messages?.OrderByDescending(m => m.Timestamp)
.FirstOrDefault()?.Content ?? string.Empty;
}
I wondered which is better practice in ASP.NET MVC, or if there is altogether a better way of doing this?