Sending back a different model from the view - c#

I want to send details of 2 different models to the view so I do this with a view model.
namespace Apps.Models
{
public class viewmodel1
{
public App app { get; set; }
public List<Colleague> colleague { get; set; }
}
}
app being a model that stores a variety of properties about an application, and colleague being a model that stores a variety of properties about colleagues.
Originally I was only passing in app, but I want to be able to display a drop down list of the colleagues first names in this view when creating an app (because the two are linked) so i need to pass in all the current colleagues to get their first names. This part is working.
However, my action result needs to change when the form is submitted to take in this new viewmodel type, and I don't know how to access the properties from the action result. Normally when you bind include there are just properties in the model, but i want to include the properties that are WITHIN the objects the viewmodel has. I don't know how to do this or of i am just doing something wrong.
I would obviously like to retain the validation that is already written for the app properties, but I'm not sure I can do that this way.

Not sure if this is the answer to your question without seeing the xaml binding you are trying to use, but you can use bindings that dive into objects.
So if you have an Employee object that is your DataContext (Employee would be your ViewModel although it has no controller logic, so I guess it's just a model here):
public class Employee
{
public string Name {get; set;}
public EmpAddress Address {get; set;}
}
public class EmpAddress
{
public string Street {get; set;}
public string Zip {get; set;
}
You can do bindings that look like this:
<TextBlock Text={Binding Address.Street}/>
Let me know if this isn't what you were after and I'll try to help.

Related

Understanding Model & ViewModel in WebView/WinForm in MVP/MVC

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.

How do I 'inherit' a class properties to use with Entity Framework

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

Do formatting helper methods belong in the model, the view model, or a separate class?

I have a model that stores company information, including tax IDs. In the US, these are 9 digit numbers and are typically displayed as ##-#######. However, in my system, I am storing these as strings with no hyphen - since other countries can have identification numbers that differ in length and format, I don't want be limited to a US standard.
Now I want to program my views to display US tax IDs in their "friendly" format. I have this working right now with a helper method I put in the Company model class:
public string FormatTaxID(string TaxID)
{
if (Address.Country == "United States")
return Regex.Replace(TaxID, #"(\d{2})(\d{7})", "$1-$2");
else
return TaxID;
}
Then in my view, I'm using:
#item.FormatTaxID(item.TaxID)
This all works fine, but it doesn't feel right to store a method like this in the model - it feels like this is more of a view/view model responsibility than a model responsibility, as it is solely for presentation.
I am using view models and thought of putting it there, but I I have multiple view models for the underlying model and don't want to repeat code if I don't have to. Also, my view model for the index uses collections and I'm not sure how I would work the method into it:
public class CompanyIndexViewModel
{
public IEnumerable<Company> Companies { get; set; }
public IEnumerable<Document> Documents { get; set; }
}
How would I apply this method to a collection like that?
Another option is creating a new helper/utility class and sticking it in there. What would MVC convention dictate?
For one-offs, I'd say use the view model. If it's something that you will reuse over and over, move it into a utility class that your views/view models/etc. can reference.
And, there's technically nothing wrong sort of doing it both ways. Put the method in a utility class and then add a property to your view model that returns this, e.g.:
public class CompanyIndexViewModel
{
...
public string TaxID { get; set; }
public string USFormattedTaxID
{
get { return Utilities.FormatTaxID(TaxID); }
}
}
The localized-to-the-Company-context TaxID of the company is properly a property of the Company, and is not a presentation detail.

What is the model in MVVM for?

I have read several articles, tutorials and blog posts about the MVVM pattern. However there is one thing I don't understand. Taking the three "layers":
Model
View
View Model
As far as I have understood MVVM the model contains the "raw" data, e.g. a name and address in case of a Student class. The view model exposes properties to the view which represent data of the model.
Example for a property in the view model
public string Name {
get { return model.Name; }
set { model.Name = value; }
}
Example for the model
private string name;
public string Name {
get { return name; }
set { name = value; }
}
This might sound a bit stupid but doesn't this create a redundancy? Why do I have to keep the name in the model and in the view model? Why should one not handle the name on the view model completely?
In such a simple example, this answer would be yes (it is unreasonably redundant). But, presumably, a page will contain more than just a single Model object. You may have the page state as well as multiple other Model objects which must all be tracked. This is done in the ViewModel.
For example, you may have additional information about the logged in user displayed in a status bar, as well as a service running to detect changes to a text file.
You may also have a form for editing the Student object. If you intend to validate those changes, then you wouldn't want to directly edit the Student object until after the modifications have been verified. The ViewModel can act as a temporary storage location in such a case.
Note on the above: It is not uncommon for validation to occur in the Model, but even then you will probably want the user to be able to enter invalid values while in the process of editing a form. For example, if your Model does not allow a zero-length value in a field, you still want to enable your user to delete the value, move to another field (say, for example, to copy it) then return to the field and finish editing (paste). If you are tied directly to the Model, then your validation logic may not handle this "in-between", "not-yet-finished" state as you'd like. For example, you might not want to accost your user with validation errors until they've finished and clicked 'Save'.
You will also probably have Command objects in the ViewModel to handle button clicks and the like. These would be domain-specific objects that would be useless in a Model.
ViewModels are also useful when you need to filter or somehow temporarily "modify" Model objects to get something useful on the screen. For example, you may want to display a list of all the Users in a system along with a real-time list of the top ten performers among them (updated every 10 seconds). Or you may want to show a list of Reports and a graph showing the overall usage rate, etc. Filtering, sorting and customizing that data would take place within the ViewModel.
The Model, on the other hand, is typically as pure as possible. Ideally, you want only POCOs that (usually) model exactly what's in your persistent storage (database, or what have you). If your persistent storage has FirstName and LastName fields, then so would your Model. Only in your ViewModel would you combine them to get a Name field (either "First Last" or "Last, First" depending on the View's needs).
For example:
namespace Model
{
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Class
{
public string Name { get; set; }
public float Score { get; set; }
}
}
namespace ViewModel
{
public class EditStudentRecordViewModel
{
private Model.Student _student;
private IEnumerable<Model.Class> _studentClasses;
/* Bind your View to these fields: */
public string FullName
{
return _student.LastName + ", " + _student.FirstName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Model.Class> PassingClasses
{
get
{
return _studentClasses.Where( c => c.Score >= 78 );
}
}
public IEnumerable<Model.Class> FailingClasses
{
get
{
return _studentClasses.Where( c => c.Score < 78 );
}
}
public void Save()
{
List<string> l_validationErrors = new List<string>();
if ( string.IsNullOrEmpty( this.FirstName ) )
l_validationErrors.Add( "First Name must not be empty." );
if ( string.IsNullOrEmpty( this.LastName ) )
l_validationErrors.Add( "Last Name must not be empty." );
if ( l_validationErrors.Any() )
return;
_student.FirstName = this.FirstName;
_student.LastName = this.LastName;
Model.Utilities.SaveStudent( _student );
}
}
}
The model is the object graph that contains your business logic.
That's where you hold the behaviour (validation, calculation and such).
The ViewModel is something that models the UI and its interactions.
These are different and have different reasons for existing - the point of the pattern is to separate your display logic to the VVM (View and ViewModel) and have your business logic completely separated.
The view model is where you would keep track of properties that are specific to the view and not necessary to the model.
Let's take your model, assume it's called Person.
And then you create a view model for Person called PersonViewModel, which looks like this:
public class PersonViewModel
{
public Person Person { get; set; }
}
(Note, you might not want to expose the model like this directly, but that's another story)
Now let's say that you have an button in the view which is used to save the Person instance. To provide a better user experience (UX), you want to enable the button only if your model has actually changed. So you implement the INotifyPropertyChanged interface on the Person class:
public class Person : INotifyPropertyChanged
{
...
Now, you could expose a HasUnsavedChanges property from your Person which the Enabled property on the save button would bind to, but that logic has nothing to do with the person.
This is where the view model comes in. You would define this view-specific property on the view model, like so:
public class PersonViewModel
{
public Person Person { get; set; }
public bool HasUnsavedChanges { get; set; }
}
Then, your view model would subscribe to the PropertyChanged event of the INotifyPropertyChanged interface, and toggle the HasUnsavedChanges property on the view model.
Then, if the binding is set up correctly, the save button would enable/disable when any change happens on your model, but your model doesn't have any logic tying it to the view.
Note that you'd have to also implement INotifyPropertyChanged on the view model as well for your view to pick up when changes are made to the view model it is bound to.
Again, the point is acting as a bridge to contain the logic that is a combination of model properties and view properties that don't belong on the model.
Model in MVVM is exactly the same as in MVP or Model2 MVC. It is the one part of MVC-inspired patterns that is not affected by variations on the theme.
Model is the layer which contains repositories, units of work, domain/model objects, data mappers, services and some other structures. All they combined create the model layer, which contains all of the domain business logic for the particular application.
Model is not any single instance. Anyone who tels you otherwise is full of it.
The specific usecases, for which MVVM has been designed, are situation, when you are unable to modify either the model layer or view instances, or both.
P.S. Though, if you are using ViewModel instances as per ASP.NET MVC documentation, then you actually are NOT using MVVM. It is just Model2 MVC with different names for things (where "viewmodels" are actually views and "views" are templates). They kinda messed up when they marketed Rails-like architecture as "MVC".
I've always viewed Models as the "Building Blocks" of the application. They are usually self-contained classes with some properties and perhaps some rudimentary validation or logic for its own properties only.
View Models on the other hand are my actual application classes that end up using the "building blocks" (Models) when building and running the application. They do things like perform advanced validation, process commands, handle events, any kind of business logic, etc.
It should be noted that you don't have to expose your Model's properties in your ViewModel like you have in your example code. Doing so is the "MVVM purist" approach as it completely separates your Model layer from the View layer, however it's also perfectly acceptable to expose the entire Model to the View instead. This is what I typically use in most small projects due to it's simplicity and lack of code-duplication.
public MyModel CurrentModel
{
get { return _model; }
set
{
if (_model != value)
{
_model = value;
RaisePropertyChanged("CurrentModel");
}
}
}
However if there are cases where only a few properties from the Model is needed in the View, or if the project is large enough where I'll want to keep the layers totally separate, then I expose my Model's properties to the View through the ViewModel like you have in your example code.

MVC 3 2 models in a view

I am new to MVC (i.e. the last few days) and i would like to know if what i have done is the best way.
I have a view that is a combination of an insert item form with a list details form underneath for a particular entity. As such i kind of need 2 models for the page in order to avoid doing things like #Html.LabelFor(model => model.FirstOrDefault().EventTypeID, "Event Type").
What i have done is set the model to be Tuple<IEnumerable<Event>,Event> that way i have both the single item and the collection of items. Can anyone suggest a less hacky alternative or is this the best way of doing this?
There are 2 solutions.
You should create a different View Model Class (a simple class with both models as properties)
You can assign it to the ViewBag.Model1 ... ViewBag.Model2 ... But this is dynamic so you will have no intellisense and you can get errors at runtime.
You should use a ViewModel like this
public class ViewModel
{
public TypeOfYourModel MyModel1 { get; set; }
public TypeOfYourModel MyModel2 { get; set; }
}
I suggest you create a ViewModel that would contain both objects you want to pass.
public class NewEventViewModel
{
public Event NewEvent { get; set; }
public Event EventDetails { get; set; }
}
You could also use ViewBag, but it is not strongly typed so you would not get IntelliSense.
I would create a Model object just for the view, with 2 properties, one for the single entity and one for the collection, and then you can pass this composed object as the model for the view

Categories

Resources