I am trying to understand and implement different UI patterns in .NET to see the pros and cons and where they suite best.
I understand the main concept but I was creating an app and a question appeared.
Say we have a class Customer, which represents the core Information of a customer.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public string PhoneNumber { get; set; }
}
Now, if I create a WebView or WebForm to show all customers I can use this class to set as source f.e. to a DGV, being able to show all properties above.
But then I want to show for example a View/Form with the Revenue history of each customer.
So there is a class CustomerRevenue like
public class CustomerRevenue
{
public Revenue ActualYearExpectedRevenue { get; set; }
public IList<Revenue> RevenuePerYearList { get; set; }
public decimal ActualYearProjectedRevenue => CalculateYearProyection();
public decimal CalculateYearProyection(int year)
{
var daysInYear = DateTime.IsLeapYear(year) ? 365 : 366;
var actualYearRevenue = RevenuePerYearList.SingleOrDefault(x => x.Year == year);
var dayNumber = DateTime.Now.DayOfYear;
var projection = ((actualYearRevenue.Amount * daysInYear) / dayNumber);
return projection;
}
}
Here, to set RevenuePerYearList we need some time, since let's say we sell a lot and have a huge list of sells with huge lists of articles, so the calculation needs some time.
So now my question:
Should I then have "concrete" classes for each view/model with the data I want to show, i.e. here I would have apart of Customer class, say a CustomerRevenueModel
public class CustomerRevenueModel
{
private readonly CustomerRevenue _customerRevenue = new CustomerRevenue();
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public CustomerRevenue CustomerRevenue
{
get { return _customerRevenue; }
}
}
}
which has (maybe) different properties, so I need to load this "heavy" properties when needed
or
should I stay with only one class (I mean, a customer always has a revenue) and leave the properties "empty"?
The first option makes me have a lot of classes, one for each view/form I want to show data for (maybe being able to reuse some models in various views/forms) but keeps all clean and in a valid state. And also each class can have it's own logic (domain logic - DDD)
The second option is less classes, less code, but some way I end having a huge (God) class, with all the properties a Customer has and all it's logic (methods). I load only the ones I need, but this appears really bad to me.
The third option is to have the big class with all properties and methods as my (domain)model, and create a "ViewModel" (which contains no methods, only props) each time I need to show sth. like above , using it as source for my GridView. This is the solution with more classes and code (big class + ViewModels + (maybe) DTOs), but also the more organized and SOLID design to my eyes... Here the use of a Mapper like AutoMapper would really help, mapping between objects
But this is the part I'm confused about...
Are these "ViewModels" a bad pattern using MVC or MVP?
Are this the same as the VM in MVVM? Which I Think not, since I've understood VM in MVVM like a "template", but what I talk about appears to me more like DAOs??
Or they don't have nothing to do, are just DAOs
I think I am a bit confused about all the different meanings of Model, ViewModel etc, in the different design patterns.
I am hardly trying to understand right MVC,MVP,MVVM and DDD and I think sometimes I am mixing terms...?
First, try to not "mix" things from different patterns, ViewModels are for MVVM, and you NEED ViewModels if you want to implement MVVM (ASP.Net MVC uses something called ViewModels, but it is not the same than the ViewModels in MVVM design pattern)
The ViewModel is like a model for the View. The ViewModel work is to "convert" the Model(s) to something the View can understand.
You can have one o more models (or none) and use it in the ViewModel, you have a ViewModel for each View.
In your example (a datagridview) you can have a model that will represent the data in a datagridview, a DTO if you want, and you can have a property in the ViewModel, a List and you will fill with data loaded from the database. In the View, you will bind that property (the list) to the dgv datasource.
Think that the ViewModel is something like the code behind of the view, but you are working with properties and commands that will be binded to controla in the view.
Related
I want to add a new property on my class, make it strongly typed so I can use it in my views and controllers, I've tried to inherit the properties, but Entity Framework or C# throws me errors...
I have this class:
public class Patient
{
public int Id { get; set; }
public string Message { get; set; }
public string FirstName { get; set; }
.....
}
which has a lot more properties in it, but shortened here.
I have a razor view, which is uses 'Patient' as it's model
using model Project.Models.Patient
So I had completed my view (or so I thought) and was asked to add functionality in the view. The functionality is to send a POST using a form of a 'Message' (a simple textarea in html). I've already got all the details I want, but this new 'Message'
So I thought, because I don't want this field in the database I could add it like this:
public class Patient
{
public int Id { get; set; }
public string Message { get; set; }
public string FirstName { get; set; }
[NotMapped]
public string Message { get; set; }
.....
}
But I'm not a fan of this, it doesn't relate to the Patient in any other way.
So I thought I could change my model in razor to something like this:
#model Project.Models.DTOs.PatientMessage
and inherit the Patient class and all it's properties (so I don't have to retype and copy past the fields again) and the new PatientMessage class would look like this:
public class PatientMessage : Patient
{
public string Message { get; set; }
}
But when I refresh my application, I receive a message stating the Application Database Context has changed, and I have to update this. I don't want to update my database, and I can't really see why I need to, it's an extra field which I don't want to include in my database.
So then I decided to make this class an 'abstract' class
public abstract class PatientMessage : Patient
{
public string Message { get; set; }
}
When I refreshed my page this time, I saw no need to update the Database, great I thought, and when I went near a page where the model was
#model Project.Models.Patient
I received this message
The abstract type 'Project.Models.DTOs.PatientMessage' has no mapped descendants and so cannot be mapped. Either remove 'Project.Models.DTOs.PatientMessage' from the model or add one or more types deriving from 'Project.Models.DTOs.PatientMessage' to the model.
MY QUESTION
Can I include this one field, without placing it on the Patient class, ideally without having to update models in my razor views, or would I have to change the models in the views and controllers and update the information to include the message and map all the details from a 'PatientMessage' to a 'Patient'
Please let me know if you need any further information.
Regards
I have an ASP.Net MVC 5 (C#) application and I'm giving my users the ability to like posts and comments.
for this I have a Model called Likes with the following Properties:
public class Like
{
public Like()
{
this.CreatedUTC = System.DateTime.UtcNow;
this.isActive = true;
}
public long id { get; set; }
public string UserID { get; set; }
public bool isActive { get; set; }
public LikeType Type { get; set; }
public DateTime CreatedUTC { get; set; }
}
Type is an enum and it can be either Comments or Posts. I've also added the following Navigation Property to both Post Model and Comment Model:
public virtual ICollection<Like> Likes { get; set; }
My question is, can I have a setter function in the above line of code where it would automatically set Comments and Posts for the Like type? I know I can use the Value variable in the Setter but using Google I couldn't find how to use it for complex types as I have above (Like).
I'm sure this would be a better way of doing this than in the repository manually set that enum every-time I'm going to save a like.
UPDATE:
Seeing how we're starting a nice little conversation about this Questions, I will throw another alternative in the mix.
How about two Tables with a base class of Like, one CommentLikes and the other PostLikes Seeing that the size of this table will grow really fast, I'm thinking separating them would possibly be a good thing, Right?
I'd rather drop the "LikeType" and either have Comment and Post entity in the Like entity and distinguish by one of them being null or introduce two new entities
public class CommentLike
{
public Comment Comment { get; set; }
public Like Like { get; set; }
}
which holds a comment and a like and PostLike which holds a Post and a Like. The Comment then looks like this
public Comment
{
public virtual ICollection<CommentLike> { get; set; }
}
Another alternative is to create separate tables for comment and post likes. While what you ask for is definitely doable I would recommend more verbose but simpler solution which will result in code that is easier to maintain and has less bugs. Is there any specific reason you want to have a LikeType property?
I had same problem but didnt encounter an easy way.
class Post{
public virtual ICollection<Like> Likes {set;get;}
}
class Comment{
public virtual ICollection<Like> Likes {set;get;}
}
Then:
class Like{
//....
}
You dont need a bi-directional relationship. Do you have a case where you need to query Likes table? and if you do, you will have to manage parsing it as ENUM somewhere which can be an extension method.
EF will create Post_Id and Comment_Id implicityly in your table design. You wont be able to query it but you wont need to. IN my experience i never needed to.
My question is, can I have a setter function in the above line of code
where it would automatically set Comments and Posts for the Like type?
I assume you are using T4 template or the classes that were generated by EF are partialthen you can extend it by creating another partial class and a wrapper property for Likes
// Backing field
private ICollection<Like> _likesWrapper;
public ICollection<Like> LikesWrapper {
get {
// Lazy loading
if(_likes == null)
{
// Just create a new list or load it from the database.
_likes = new List<Like>();
}
return _likes;
}
set {
foreach(var val in value)
{
//Set the comment and posts
}
Likes = value;
}
I am little confuse on the ViewModel design with Inheritance.
Scenaro:
I have a datamodel and multiple viewmodels of User Enity. I am using ADO.Net to fetch from DB bind to datamodel. And the datamodel can be passed to different ViewModel.It seems Ok with one or two views. But When number of my Views increases, I need different ViewModels. Also I want to avoid redundant fields in my ViewModel. And I create a UserBaseModel. So all ViewModel inherit from it
Problem:
I have password and confirm password fields for UserSetting Views and UserRegistration view and I create UserSettingViewModel and UserRegistrationViewModel. And I dont think other viewmodel do not require this fields. I dont want to define the fields in UserBaseModel and also I dont want to define multiple times for the same fields in both ViewModels.
Is there any alternative? Suggestions and advices are welcome
Since C# doesn't support multiple inheritance you can't derive the models from a second base model. You basically end up with creating another base view model which derives from UserBaseModel and contain the password properties:
public UserBaseModelWithPassword : UserBaseModel
{
public string Password { get; set; }
public string PasswordConfirm { get; set; }
}
Then you can derive UserSettingViewModel and UserRegistrationViewModel from it.
Little more thoughts give me another solution.
public PasswordModel
{
public string Password { get; set; }
public string PasswordConfirm { get; set; }
}
public UserSettingViewModel
{
public PasswordModel Password { get; set; }
}
I am trying to separate/refactor code into folders and move all my 'Fill' properties into a logical place.
Is there a technical name for populating properties using a function
example:
public class AccountsView
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
This would be place in its own Class .. right now its within the above class
public static AccountsView FillCustomerView(Account data)
{
view.Email = data.Email;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
return view;
}
What would this 'FillCustomerView()' function be called?
The concept described here is called object mapping, and in this example it is implemented as a method on view model.
The drawback of this implementation is that it couples the view models to domain models, and this is usually frowned upon. To avoid this, mapper objects are typically used - they define projection from one model to another.
You could use some already existing implementation. Most popular seems to be Automapper, but there are others. E.g. the excellent ServiceStack framework also supports it.
Ok I've been trying to figure out the best way to do this for a few days, but still haven't come up with a very elegant answer so am hoping I someone can point me in the right direction or give some peer review :)
Basically I have 3 classes (they are different and much more complex than these):
public class Person
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Place> { get; set; }
}
public class Place
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Thing> { get; set; }
}
public class Thing
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Place> { get; set; }
virtual int PersonID { get; set; }
}
So basically you have Persons, who have many Places, which can have many Things which can also appear in multiple Places (trying to reduce having to store duplicates of Things) but only for that Person
What is the best way to setup my ViewModel to handle this? Should I just create everything by itself using Ajax and Json (what I've been doing) or is there a way to handle this type of relationship in a ViewModel and single post back to the server?
Currently I'm doing the following:
Fill out Person form -> ajax save to server, get Person ID
Fill out Place form (including Person's ID) -> ajax save to server, get Place ID
Fill out Thing form (including Person ID and Place IDs in a delimited string
I know there should be an easier way to do this as its kinda bulky, but since its all query string I can't figure it out
You say "kinda bulky," but I think it tends to be more lightweight if you can build an object graph on a form in real time by using AJAX/JSON, probably against a RESTful API, somewhat as you describe.
The alternative is using script (jQuery, JSMVC, Knockout) to build a form and POST the whole sucker at once. I've had to do this in some situations where none of the data should be persisted until the whole graph is committed. The trick here is understanding ModelBinder and how it builds/updates that graph for you.
If this is what you were asking, I can expand on the key points of how ModelBinder deals with complex object graphs and collections.
I answered a similar question about how to handle this using interfaces and partial views.
How to create Asp.Net MVC 3 view model