ASP.NET MVC 3: unobtrusive JavaScript validation - validation

There are a lot of examples on how to "create your own model". Mark them with DataAnnotations. Scott Guthrie explains how to validate your model when using an ORM. What I don't find is when your model is actually coming in from an external DLL. How do you validate it?
Example:
/* Class coming in from an third-party DLL file. */
public class Person
{
public string Name{get;set;}
public int Age {get;set;}
}
The solution I am thinking of: Inherit the external class and then apply [MetadataType] to the inherited class.
[Metadata(typeof(Person2_Validation))]
public class Person2:Person{}
public class Person2_Validation
{
[Required,Stringlength(50,ErrorMessage="Name required"]
public string Name{get;set;}
[RegularExpression("([0-9]+)")]
public int Age
}
Is there a better way?

You could create a model and use a Mapper (like AutoMapper or EmitMapper or ValueInjecter) to map between your objects, and validate against the mapped model.
When you need to transfer the object back you can map between your model to the recieved model.
This is very similar to a ViewModel approach in ASP.NET MVC.
So it's something like this:
Class A (the class from the DLL)
Class B (your model)
You set all your annotations on B, and create whatever properties you need.
What you use is B. When you get something from the repository/source you map (copy all relevant values) A=>B and send it (let's say as a model in a View).
When you receive B back you validate it, and then map it the other way B=>A, and send it to the repository/service.
BTW: I would recommend using this approach even if model A was YOUR class.
Why use ViewModels instead of Domain Models in Views.

#Linkgoron answer is true. You are searching view model vs domain model. we need to think the model from dll is a domain model and map it to our own view model as we did even when dealing with our own repository/persistence. it is a best practice. don't worry about mapper, it will map automatically.
See this example:
http://weblogs.asp.net/shijuvarghese/archive/2010/02/01/view-model-pattern-and-automapper-in-asp-net-mvc-applications.aspx
See this #Nick DeVore answer why view model instead of domain model here
Why Two Classes, View Model and Domain Model?
and also
Bestpractice - Mixing View Model with Domain Model
Your issue could be one of the reason why :)

Related

Making descendants of generic form visible and editable in VS designer

I'm trying to create a base form using generics, so I could do sth like this:
public class GenericForm<T> : Form where T : IEntity
And then:
public class ManageCustomerForm : GenericForm<Customer>
But I'm not able to view ManageCustomerForm's designer. I understand it's because VS attempts to create an instance of GenericForm but doesn't know what type to use on T.
So I tried some solutions using TypeDescriptionProviders, cause it works for the case in which the base form class is abstract. But it doesn't work either. Is it possible?
One detail is I'd like to avoid to create an intermediate class like this:
public class GenericForm<T> : Form where T : IEntity
public class ManageCustomerIntermediateForm : GenericForm<Customer>
public class ManageCustomerForm : ManageCustomerIntermediateForm
I imagine that Customer is data for the form. Instead of binding the data to the form, use a separate data class for the Customer. DataBinding can be used to tie the user interface controls to the data source.
Another idea is to use the Model-View-Controller design pattern to separate the form (the view) from the model (the customer).

how to synchronize data annotations between model and view models

I'm working with EF Code First, so my data annotations are driving my SQL server database columns definitions/properties (i.e., [StringLength(30)] = nvarchar(30), etc.). I'm using ViewModels to drive my views. How can I synchronize the data annotations between Models and ViewModels?
For example, I have the following entity class:
public class Ticket
{
...
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:C}")]
public double TicketBalance { get; set; }
...
}
And a ViewModel that uses the same property from the Model class:
public class EditTicketViewModel
{
...
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:C}")]
public double TicketBalance { get; set; }
...
}
How can I synchronize these two data annotations?
While you can't change the attributes on your ViewModels at runtime, you can to some degree emulate them for the purposes of validation (which is presumably the reason that you're using data annotations).
This requires creating the ViewModels using an object mapper like AutoMapper or EmitMapper. You can then hook into an appropriate part of the mapping process to update the DataAnnotationsModelMetadataProvider and DataAnnotationsModelValidatorProvider, which are used by MVC in the various parts of the validation process.
This answer shows a way of doing it with AutoMapper. I'm currently having some fun looking at a solution with EmitMapper, since that's somewhat faster to execute.
There is no synchronization between the two. While they may look similar, they actually are different: one is for the database, another is for the GUI.
For the database you mainly want to test for [Required] and [StringLength(XXX)]. Sometimes [DataType] as well.
For the GUI you want to check for those in addition of formatting, regular expressions, ranges etc.
There are validation attributes, display attributes, data modeling attributes. Choose the right attributes category at the right place according to the situation.
And it gets even worse when you start using things like jQuery validation or KnockoutJS validation. In that case you will have to duplicate your efforts third time for JS purposes. Unfortunately.
You can also check what other folks did here: How do I remain DRY with asp.net mvc view models & data annotation attributes?
There folks use inheritance. which is fine, but a bit confusing while you let others read your code later on.
The good advise is to switch from data annotations to fluent validation as per one of the responses in the link above. It will allow you to apply the same validation class to multiple models.
Hope this helps.

Where to put the ViewModel

I have a viewmodel that can be use in the Controllers, View, and Core. The Core is a seperate project while the Controllers and View is in the Web Project. Where is the best location to put the ViewModel, is it in the Web project or in the Core, or do I need to created a seperate project for the View Model only?
I have a viewmodel that can be use in the Controllers, View, and Core.
No. You are not using it in the Core. Google "Separation of Concerns". The responsibility of the view model is to represent the Model (the Core project) in the view. It should not be used for anything else. I've written about view models here: http://blog.gauffin.org/2011/07/three-reasons-to-why-you-should-use-view-models/
It's the controllers responsibility to take everything from the Model (core
project) and create an appropriate view model.
Putting the view model somewhere so it can be used in the Core gives it more than one reason to change which will break the Single Responsibility Principle (one of the five SOLID principles). What it means is that several parts of your application will be affected by every change that you make and it will likely lead to small workarounds or quick fixes which will give you a maintenance nightmare in a year of so.
Update
Example using AutoMapper:
public class FlairController
{
public FlairController(IYourServiceOrRepository repos)
{
}
public ActionResult Details(int id)
{
SomeCoreObject entity = _repos.Get(id);
FlairViewModel model = new FlairViewModel();
Mapper.Map(entity, model);
return View(model);
}
}
Your example code (in the comment) is how the method would look like without a mapping framework.
Since ViewModels are specific to the Views, I would usually create a ViewModel folder under my UI project and keep it there.
I will create a seperate Service Layer ( another project) for bridging data between my ViewModels and Entity Models. My Controller Action methods call the service layer with the ViewModel object.
The view model is typically a wrapper around the model that has the UI formatted data. You should probably keep your model class in the Core project and the view model class in your web project.
The constructor for your View Model class can take an instance of your model class (and any other objects you need to populate your view) and generate the proper view data. For example, if you model has a DateTime object, then your view model could have a corresponding String property that contains the DateTime in the format you want to show.

Serialize VM vs state class

After my wonderings on the events registration (you can find here ViewModel Event Registration and ViewModel Lifetime), now I'm thinking about viewmodel tombstoning:
In case of Tombstoning, is the ViewModel serialization a good approach ?
I'm thinking about the case in which different viewmodels have a reference to the same class. In case of Viewmodels serialization and deserialization the referenced class instance could have duplicated instance, isn't it ?
Wouldn't be better to have specialized state classes whose unique purpose in to contain all the app data, everyviewmodel get data (i mean reference to the data) from there and update the data in there and the app think only to serialize those specialized class ?
Any experience on this subject is appreciated.
Regards
SkyG
Caliburn Micro has a lot of this built in to the framwork allowing you to save properties of a view model or the entire graph to both phone state and app settings. You just need to create a class and inherit from StorageHandler.
public class PivotPageModelStorage : StorageHandler<PivotPageViewModel>
{
public override void Configure()
{
this.ActiveItemIndex().InPhoneState().RestoreAfterViewLoad();
}
}
And to your other posted question. CM has a nice way of handling the forced view first approach on the phone. It allows you to do page navigation by specifying the VM and it will handle the rest. And as a bonus, if you specify parameters to pass CM will pull them off the query string and populate properties on the target VM.
public void GotoPageTwo()
{
navigationService.UriFor<PivotPageViewModel>().WithParam(x => x.NumberOfTabs, 5).Navigate();
}

MVC: Am I doing it right?

Hey people. I don't know if I understood 100% the MVC concept.
I'm having troubles with the Model-View relation.
In order to present the data to the user, the View must have access to the data, right?
Is this access obtained by passing all the needed data to the view directly (and having the view hold the data within its class as an attribute), or just obtain the data "parsed" as strings, integers, etc... as it is needed (as the user navigates through the GUI) from the controller, by raising events? I feel like this is a little bit event overkill, since the data hasn't changed.
BTW, can you tell me what those arrows on the MVC diagram on Wikipedia do on a real example? Thanks.
A view is for presentation purposes only. The controller is in charge of fielding requests from the UI and invoking the necessary methods in the model, which then present their outputs to the views.
The arrows denote relationships between the classes. The dotted lines are relationships between classes and interfaces while the solid lines denote direct relationships, meaning that the classes likely hold instance variables of the classes they are related to.
The model is the central, authoritative repository of information. As an example, take a church's directory of its congregation.
There are controllers into that model that inform the model of data that should be changed. As an example, a congregation member informs the church office when they move or change phone numbers, and the directory is updated.
There are also views into that model that use the data, but cannot make changes to it. As an example, one church member can get information about another from the directory.
Note that in some cases views and controllers can be the same thing, or views for one model, controllers for another, etc., etc. For example a church member can be a view into other members' data, or change their own by interacting with the model.
The important thing to keep in mind is who owns the authoritative version of the data. The invariant that it is the model that has the most timely, accurate and authoritative data means you know exactly where to go to get the information you need.
There are two basic ways a model can communicate with the views: pushing and pulling. Pushing the data involves intelligence on the model side to know which views should be notified when a piece of information has been updated. Pulling the data involves intelligence on the view side to know how and when to look at the model for changes to the data it is most interested in.
To build on the previous answers, here is a super simple application showing the various usage of each of the areas in question. This app stores and displays cars which a Salesman has sold.
First we have our models:
public class Car
{
int Id { get; set; }
string make { get; set; }
string colour { get; set; }
}
public class Salesman
{
int Id { get; set; }
string name { get; set; }
IList<Sale> Sales { get; set; }
}
public class Sale
{
int Id { get; set; }
int CarId { get; set; }
int SalesmanId { get; set; }
decimal Amount { get; set; }
}
Now lets say we need to display a page which details all of the cars which a particular Salesman has sold. To do this we decide what data we will need on the page, e.g. Salesman name and a list of Car's which he has sold. We create a View Model of this data.
public class SalesViewModel
{
string SalesmanName { get; set; }
List<Car> CarsSold { get; set; }
}
Now we need to build (populate) this View model in our controller ready to be passed to our View.
public ActionResult SalesmanCarsSold(int salesmanId)
{
SalesViewModel salesVm = new SalesViewModel();
using (var dbCtx = new dbCtx())
{
salesVm.SalesmanName = dbCtx.GetSalesmanById(salesmanId).Name;
salesVm.CarsSold = dbCtx.GetCarsSoldBySalesmanId(salesmanId);
}
return View(salesVm);
}
Now all there is to do is just write this data out to our view, e.g.
#model MyProject.Web.Models.ViewModels.SalesViewModel
Salesman Name: #Model.SalesmanName
#foreach(var car in Model.CarsSold)
{
Car: #car.make
}
I believe I can add a little clarity. Basically you can use a Singleton pattern where only one instance of the model exists then you can use said Singleton within the View to bind things in your View to the model, that is you add listeners for changes to the model (in one sense or another) and the view updates itself whenever the model changes.
The model itself isn't affected directly by the view rather the view dispatches events or otherwise uses the controller to modify the model. This way you can have a common "shared" model a common controller which modifies said model and all sorts of views that display parts of said model in ways that make sense.
The views don't need to handle passing around data between one another in this way and the common functionality of modifying the model is contained in the controller. I had some trouble with these concepts when I first dove into them as well mostly because you never have 100% true separation of these parts, they are all related and will have a references to one another (via attached listeners at the least).
In Flex/AS3 my dev environment of choice this is very very easy to accomplish, you make on Model.as file that has a static variable called say modelLocator which is itself a new Model(), in the Model.as you define all your public variables, in Controller.as you have a handle on the model by creating a property (sure call it modelLocator here too) and within the controller's constructor you can instantiate the modelLocator like modelLocator=Model.modelLocator, do the same in your View then in the view you just update your view components when the model changes (in Flex you can use {} to bind values directly onto properties of your components, views pull from the model based on the post from #fbereto, good explanation btw).
From a high-level view, when you think about application architecture i.e. data layer, business logic layer and presentation layer, MVC should only be your presentation layer. I have often seen people make the mistake of thinking that in MVC, models represent their data layer, controllers represent the business logic layer and views represent the presentation layer.
You should always have a separate business logic layer (or services layer) which your MVC controllers access to carry out business logic, and also a separate data access layer (or repositories) which is only accessed by your services/business logic layer to retrieve data out of the database.
In your typical MVC application, you may have multiple view models representing the same data layer object (which typically represents a database table). For example, you may have 2 views for to represent information about a person; one is a summary view and the other is a details view. In your MVC application you will have 2 View Models i.e. PersonSummary and PersonDetail both of which are populated from the same Persons table in the data layer and are returned to your Controller Action when your controller calls methods (e.g. GetPersonSummary() and GetPersonDetails()) on the PersonService class (business logic layer).
Layering your applications in this way will make them far more maintainable and testable than treating your View Models as data models and writing all your business logic in the Controller actions.
This was my 2cents anyway! Hope it helps you understand MVC better...

Resources