Related
I have a Service class with a method called GetProducts(). That encapsulates business logic and calls the repository to get a list of products.
My MVC view wants to show that list of products as an MVC SelectList. Where is the correct place for that logic to go. I seem to have 3 options:
Model
The Model should expose a property called ProductSelectList. When the getter of this property is called by the View, the Model should call Service.GetProducts() and convert the result to a SelectList before passing it on.
Plausible argument: The Model should make calls to business logic and the repository. The View should merely render predetermined data. The Controller should not be involved, save for passing contextual data to the Model.
View
The View should contain code that calls Service.GetProducts() directly and converts the result to a SelectList inline.
Plausible argument: The View should call for this data directly as it is specifically for use on the View. There is no need to involve the Model or Controller, as we are calling an abstracted Service method anyway, so anything else just adds extra overhead.
Controller
The Controller should make the call to Service.GetProducts(), convert the results to a SelectList and pass it through to the Model, which should contain a simple ProductSelectList property. The View will access this property for rendering.
Plausible argument: The Controller knows which parameters to provide to the Service method, so it should make the call. The Model should be a simple placeholder for data, filled by the Controller. The View's job is to simply render the data from the Model.
I have a feeling that the correct answer is Model, but the other two make some reasonable points. Perhaps I've muddied the waters by already having a Service class that's separate to the Model?
Would anybody care to share their opinion? Is this just a matter of taste?
I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).
I have my views dumb and only displaying data.
I have my View Models store the information that the View will need, occasionally exposing 'get only' properties that format other properties into a nicer format. If my model needs access to my services, then I feel I'm doing something wrong.
The controllers arrange and gather all the information together (but do no actual work, that is left for the services.
In your example, I would have my controller action similar to:
public ActionResult Index()
{
IndexViewModel viewModel = new IndexViewModel();
viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");
return View(viewModel);
}
and my view model similar to:
public class IndexViewModel()
{
public SelectList ProductSelectList { get; set; }
public int ProductID { get; set; }
}
With the appropriate part of the view looking like:
#Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList);
This way I'm content that I know where to look if there is an issue with anything and everything has a very specific place.
However, there is no correct way as seems always to be the case with these things. Stephen Walther has a good blog series on MVC tips. In one he talks about the View Model emphasis and although not a SelectList he populates, the SelectList is still data in much the same way his list of products is.
In a classic MVC architecture your Model shouldn't be much more than a container for your view data hence the reason it's often called a ViewModel. A ViewModel is different from the Entity Model(s) that your service layer manages.
Your controller is then responsible for populating your ViewModel from the entity model(s) returned by your service layer.
Due to convenience some developers will use their service layer entities directly in their ViewModels but long term that can lead to headaches. One way around that is to use a tool such as AutoMapper to automate the shuffling of data to and from your ViewModel and entity models.
Here's what a controller might look like. Notice that data such as the SSN does not get exposed to the view since there is a mapping from your Entity Models to your View Model.
public class Customer : IEntity
{
public string CustomerID { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class CustomerEditViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string PhoneNumber { get; set; }
}
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit ()
{
Customer customer = _customerService.GetCustomer (User.Identity.Name);
var model = new CustomerEditViewModel ()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Address1 = customer.Address.Address1,
Address2 = customer.Address.Address2,
Country = customer.Address.Country,
City = customer.Address.City,
State = customer.Address.State,
Zip = customer.Address.Zip,
PhoneNumber = customer.Address.PhoneNumber,
};
return View (model);
}
}
You're right that there are a number of ways to handle this, and that's even before considering variations like MVP, MVVM, et cetera. Since you're asking about ASP.Net MVC in particular, I will defer to Microsoft:
An MVC model contains all of your application logic that is not
contained in a view or a controller. The model should contain all of
your application business logic, validation logic, and database access
logic. For example, if you are using the Microsoft Entity Framework to
access your database, then you would create your Entity Framework
classes (your .edmx file) in the Models folder.
A view should contain only logic related to generating the user
interface. A controller should only contain the bare minimum of logic
required to return the right view or redirect the user to another
action (flow control). Everything else should be contained in the
model.
In general, you should strive for fat models and skinny controllers.
Your controller methods should contain only a few lines of code. If a
controller action gets too fat, then you should consider moving the
logic out to a new class in the Models folder.
Source
I would say your call belongs in the Model.
One thing to keep in mind is that the SelectList class is specific to MVC only. So in my opinion it shouldn't be included in any business logic, and model classes fall into that category. Therefore your select list should be a part of a view model class instead.
This is the way it works in my projects:
Controller method is called
Controller uses repository (business logic, in other words) to get model data
Controller converts the model data if necessary and creates a view model object
Controller passes the view model to the view
The view displays the data in the view model with limited logic to show or hide things, etc
I'd go with option 3. In general, I'll construct my MVC apps such that the controller makes a call to the service to return a model (or collection of models) which are then passed to the view.
I generally keep my models very thin. They are a flattened representation of the data with validation attributes and that's it. I use a service (or model builder) layer to construct the models and do business logic on them. Some folks embed that into the model, but I find that makes for a messy project.
You definitely don't want the view making any calls to your services.
Update...
I'm assuming that this SelectList is your model. If instead it's a part of your model, then you're right, you should put it in your model. I generally don't like to make it a method call, though. I'd have a property on my model:
public SelectList Products { get; set; }
And have my service or model builder class actually populate it. I don't usually have any data-oriented methods on my models.
I'm going with option 1.
Models are the place to make calls to business logic, et cetera.
View - Should display only what the ViewModel already has been populated with.
Controller - the job of the Controller is to direct the traffic coming in (from Web requests) to the Logic that is responsible for handling the request. Hence the term 'controller'.
There are always exceptions to these, but the best place (structurally) is the Model.
I had this problem when I started into MVC and came up with this solution.
The controller talks to a Service Layer. The service layer contains my Domain models and does all the processing for request from the Controllers. The service layer also returns ViewModels to satisfy requests from the controller.
The service layer calls a repository and gets the entities it will need to build the ViweModels. I often use Automapper to populate the ViewModel or collections within the view model.
So, my view models contain all that is needed by the View, and the Controller is doing nothing but handling request and forwarding them to the appropriate service handler.
I don't see a problem with having view specific items like SelectLists in the view Model either.
None of the above.
In my web layer I basically just have html and javascript views. The model shouldn't leak into the view and neither should the services.
I also have an Infrastructure layer which binds the services and model to the views. In this layer there are ViewModels, which are classes that represent what will be displayed on the screen, Mappers, which do the work getting data from services/model and mapping it to the view model, and Tasks, which perform tasks such as Saving, Updating and Deleting data.
It is possible to put a lot of this infrastructure in the Controllers, similar to the example Todd Smith has given above, but I find for anything other than trivial views the Controller becomes littered with code to load data and populate view models. I prefer a dedicated single responsibility mapper class for each view model. Then my controller will look something like
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit (int id)
{
return View (CustomerEditMapper.Map(id));
}
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Save(CustomerEditViewModel model)
{
var errors = CustomerEditUpdatorCommand.Execute(model);
ModelState.AddErrors(errors);
return View ();
}
}
I'm torn between option 1 and option 3. I've ruled option 2 out completely as to me that's polluting the view with procedure calls not just presentation layer work.
Personally I would do it in the model and the getter would call the Service layer but I also subscribe to the belief that the model should only contain the information the view needs to render the page, by not fully containing the data in the model at the time you pass it to the view you are breaking this.
Another option here though would be to avoid tightly coupling the view and model by putting a Dictionary of the Products into the view through a Service Call then using the view to transform the Dictionary to a SelectList but this also gives you the ability to just output the information as well.
I think this boils down to a preference as to where you are happy having your logic.
I've made a custom model, and I want to mock it. I'm fairly new to MVC, and very new to unit testing. Most approaches I've seen create an interface for the class and then make a mock that implements the same interface. However I can't seem to get this to work when actually passing the interface into the View. Cue "simplified" example:
Model-
public interface IContact
{
void SendEmail(NameValueCollection httpRequestVars);
}
public abstract class Contact : IContact
{
//some shared properties...
public string Name { get; set; }
public void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class Enquiry : Contact
{
//some extra properties...
}
View-
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<project.Models.IContact>" %>
<!-- other html... -->
<td><%= Html.TextBoxFor(model => ((Enquiry)model).Name)%></td>
Controller-
[HttpPost]
public ActionResult Index(IContact enquiry)
{
if (!ModelState.IsValid)
return View(enquiry);
enquiry.SendEmail(Request.ServerVariables);
return View("Sent", enquiry);
}
Unit Testing-
[Test]
public void Index_HttpPostInvalidModel_ReturnsDefaultView()
{
Enquiry enquiry = new Enquiry();
_controller.ModelState.AddModelError("", "dummy value");
ViewResult result = (ViewResult)_controller.Index(enquiry);
Assert.IsNullOrEmpty(result.ViewName);
}
[Test]
public void Index_HttpPostValidModel_CallsSendEmail()
{
MockContact mock = new MockContact();
ViewResult result = (ViewResult)_controller.Index(mock);
Assert.IsTrue(mock.EmailSent);
}
public class MockContact : IContact
{
public bool EmailSent = false;
void SendEmail(NameValueCollection httpRequestVars)
{
EmailSent = true;
}
}
Upon a HttpPost I get a "Cannot create an instance of an interface" exception. I seems that I can't have my cake (passing a model) and eat it (pass mock for unit testing). Maybe there's a better approach to unit testing models bound to views?
thanks,
Med
I'm going to throw it out there, if you need to mock your models you're doing it wrong. Your models should be dumb property bags.
There is absolutely no reason that your model should have a SendEmail method. That is functionality that should be invoked from a controller calling to an EmailService.
Responding to your question:
After years of working with Separation of Concern (SOC) patterns like MVC, MVP, MVVM and seeing articles from people brighter than me (I wish I could find the one I'm thinking off about this but maybe I read it in a magazine). You will eventually conclude in an enterprise application you will end up with 3 distinct sets of model objects.
Previously I was a very big fan of doing Domain Driven Design (DDD) using a single set of business entities that were both plain old c# objects (POCO) and Persistent Ignorant (PI). Having domain models that are POCO/PI leaves you with a clean slate of objects where there is no code related to accessing the object storage or having other attributes that have schematic meaning for only 1 area of the code.
While this works, and can work fairly well for a period of time, there is eventually a tipping point where the complexity of expressing the relationship between View, Domain Model, and Physical Storage Model becomes too complex to express correctly with 1 set of entities.
To solve the impedance mismatches of View, Domain and Storage you really need 3 sets of models. Your ViewModels will exactly match your views binding to facilitate it to be easy to work with the UI. So this will frequently have things such as adding a List to populate drop downs with values that are valid for your edit view/action.
In the middle is the Domain Entities, these are the entities that you should validate against your business rules. So you will map to/from them on both sides to/from the view and to/from the storage layer. In these entities is where you could attach your code to do validation. I personally am not a fan of using attributes and coupling validation logic into your domain entities. It does make alot of sense to couple validation attributes into your ViewModels to take advantage of the built in MVC client side validation functionality.
For validation I would recommend using a library like FluentValidation (or your own custom one, they're not hard to write) that lets you separate your business rules from your objects. Although with new features with MVC3 you can do remote validation severside and have it display client side, this is an option to handle true business validation.
Finally you have your storage models. As I said previously I was very zealous on having PI objects being able to be reused through all layers so depending on how you setup your durable storage you might be able to directly use your domain objects. But if you take advantage of tools like Linq2Sql, EntityFramework (EF) etc you will most likely have auto generated models with code for interacting with the data provider so you will want to map your domain objects to your persistence objects.
So wrap all of this up this would be a standard logic flow in MVC actions
User goes to edit product page
EF queries the database to get the existing product information, inside the repository layer the EF data objects are mapped to the Business Entities (BE) so all the data layer methods return BEs and have no external coupling to the EF data objects. (So if you ever change your data provider you don't have to alter a single line of code except for the internal implementation)
The controller gets the Product BE and maps it to a Product ViewModel (VM) and adds collections for the different options that can be set for drop down lists
Return View(theview, ProductVM)
User edits the product and submits the form
Client side validation is passed (useful for date validation / number validation instead of having to submit the form for feedback)
The ProductVM gets mapped back to ProductBE at this point you would validate the business rules along the lines ValidationFactory.Validate(ProductBE), if it's invalid return messages back to view and cancel edit, otherwise continue
You pass the ProductBE into your repository model, inside the internal implementation of the data layer you map the ProductBE to the Product Data Entity for EF and update the database.
2016 edit: removed usages of Interface as separation of concerns and interfaces are entirely orthogonal.
Your issue is here:
public ActionResult Index(IContact enquiry)
MVC in the background has to create a concrete type to pass to the method when calling it. In this method's case, MVC needs to create a type which implements IContract.
Which type? I dunno. Neither does MVC.
Instead of using interfaces in order to be able to mock your models, use normal classes that have protected methods which you can override in mocks.
public class Contact
{
//some shared properties...
public string Name { get; set; }
public virtual void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class MockContact
{
//some shared properties...
public string Name { get; set; }
public bool EmailSent {get;private set;}
public override void SendEmail(NameValueCollection vars = null)
{
EmailSent = true;
}
}
and
public ActionResult Index(Contact enquiry)
It is possible to use interfaces.
See: http://mvcunity.codeplex.com/
Suppose I want to allow to select our entity (from a dropdown, etc) on a page, let's say Product. As a result I may receive this:
public ActionResult SelectedAction(Guid productId)
{
}
But, I want to use model binders power, so instead I write model binder to get my product from repository and instead use
public ActionResult SelectedAction(Product product)
{
if (ModelState.IsValid) {} else {}
}
My model binder will set model state to false if product is invalid.
Now, there're problems with this approach:
It's not always easy to use strongly-typed methods like Html.ActionLink(c => c.SelectedAction(id)) since we need to pass Product, not id.
It's not good to use entities as controller parameters, anyway.
If model state is invalid, and I want to redirect back and show error, I can't preserve selected product! Because bound product is not set and my id is not there. I'd like to do RedirectToAction(c => c.Redisplay(product)) but of course this is not possible.
Now, seems like I'm back to use "Guid productId" as parameter... However, there's one solution that I'd like to present and discuss.
public class EntityViewModel<T> where T : BaseEntity
{
public EntityViewModel(Guid id)
{
this.Id = id;
}
public static implicit operator EntityViewModel<T>(T entity)
{
return new EntityViewModel<T>(entity.Id);
}
public override string ToString()
{
return Id.ToString();
}
public Guid Id { get; set; }
public T Instance { get; set; }
}
Now, if I use
public ActionResult SelectedAction(EntityViewModel<Product> product)
{
if (ModelState.IsValid) {} else {}
}
all the problems are solved:
I can pass EntityViewModel with only Id set if I have only Id.
I don't use entity as parameter. Moreover, I
can use EntityViewModel as property inside another ViewModel.
I can pass EntityViewModel back to RedirectToController and it will keep its Id value, which will be
redisplayed to user along with the validation messages (thanks to MVCContrib and ModelStateToTempData / PassParametersDuringRedirect).
The model binder will get Instance from the repository and will set model state errors like "Not found in database" and so on. And I can use things like ActionLink(c => c.Action(Model.MyProductViewModelProperty)).
The question is, are there any drawbacks here? I can't see anything bad but I'm still new to MVC and may miss some important things. Maybe there're better and approved ways? Maybe this is why everybody uses entity IDs as input parameters and properties?
Overall that looks like a good appoach to me...
As an alternative, you could use POCO for your viewmodel then I think all 3 problems would be solved automatically. Have you seen the Automapper project that allows an Entity to DTO approach? This would give you more flexibility by separating you ViewModel from your EntityModel, but really depends on the complexity of you application you are building.
MVC's ViewDataExtensions might also be useful instead of creating custom containers to hold various viewmodel objects as you mention in number 2.
MVCContrib's ModelStateToTempData should work for any serializable object (must be serializable for any out of process sessionstate providers eg. SQL, Velocity etc.), so you could use that even without wrapping your entity classes couldn't you?
I have certain panels on my page that are hidden under certain circumstances.
For instance I might have a 'billing address' and 'shipping address' and I dont want to validate 'shipping address' if a 'ShippingSameAsBilling' checkbox is checked.
I am trying to use the new DataAnnotations capabilities of ASP.NET MVC 2 (preview 1) to achieve this.
I need to prevent validation of the 'shipping address' when it is not displayed and need to find the way way to achieve this. I am talking mainly server side as opposed to by using jquery.
How can I achieve this? I have had several ideas, related to custom model binding but my current best solution is below. Any feedback on this method?
For the CheckoutModel I am using this approach (most fields hidden):
[ModelBinder(typeof(CheckoutModelBinder))]
public class CheckoutModel : ShoppingCartModel
{
public Address BillingAddress { get; set; }
public Address ShippingAddress { get; set; }
public bool ShipToBillingAddress { get; set; }
}
public class Address
{
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "First name is required")]
public string FirstName { get; set; }
[Required()]
public string LastName { get; set; }
[Required()]
public string Address1 { get; set; }
}
The custom model binder removes all ModelState errors for fields beginning with 'ShippingAddress' if it finds any. Then 'TryUpdateModel()' will return true.
public class CheckoutModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
base.OnModelUpdated(controllerContext, bindingContext);
var model = (CheckoutModel)bindingContext.Model;
// if user specified Shipping and Billing are the same then
// remove all ModelState errors for ShippingAddress
if (model.ShipToBillingAddress)
{
var keys = bindingContext.ModelState.Where(x => x.Key.StartsWith("ShippingAddress")).Select(x => x.Key).ToList();
foreach (var key in keys)
{
bindingContext.ModelState.Remove(key);
}
}
}
}
Any better solutions?
http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html
I can see your predicament. I'm looking for other validation solutions also with regard to complex validation rules that might apply to more than one property on a given model object or even many properties from different model objects in a object graph (if your unlucky enough to be validating linked objects like this).
The limitation of the IDataErrorInfo interface is that a model object satisfies the valid state simply when none of the properties have errors. This is to say that a valid object is one where all of it's properties are also valid. However, i may have a situation where if property A, B and C are valid - then the whole object is valid.. but also if property A is not valid but B and C are, then the object satisfies validity. I simply have no way of describing this condition/rule with the IDataErrorInfo interface / DataAnnotations attributes.
So i found this delegate approach. Now many of the helpful advancements in MVC didn't exist at the time of writing this article but the core concept should help you. Rather than using attributes to define the validation conditions of an object we create delegate functions that validate more complex requirements and because they're delegated we can re-use them. Sure it's more work, but the use of delegates means that we should be able to write validation rule code once and store all the validation rules in the one place (maybe service layer) and (the kool bit) even use the MVC 2 DefaultModelBinder to invoke the validation automatically (without heaps of checking in our controller actions - like Scott's blog says we can do with DataAnnotations. Refer to the last paragraph before the 'Strongly Typed UI Helpers' heading)!
I'm sure you can beef the approach suggested in the above article up a little with anonymous delegates like Func<T> or Predicate<T> and writing custom code blocks for the validation rules will enable cross-property conditions (for example the condition you referred to where if your ShippingSameAsBilling property is true then you can ignore more rules for the shipping address, etc).
DataAnnotations serves to make simple validation rules on objects really easy with very little code. But as your requirements develop you will need to validate on more complex rules. The new virtual methods in the MVC2 model binder should continue to provide us with ways of integrating our future validation inventions into the MVC framework.
Make sure the fields you don't want validated are not posted to the action. We only validate the fields that were actually posted.
Edit: (by questioner)
This behavior has changed in MVC2 RC2 :
Default validation system validates
entire model The default validation
system in ASP.NET MVC 1.0 and in
previews of ASP.NET MVC 2 prior to RC
2 validated only model properties that
were posted to the server. In ASP.NET
MVC 2, the new behavior is that all
model properties are validated when
the model is validated, regardless of
whether a new value was posted.
Applications that depend on the
ASP.NET MVC 1.0 behavior may require
changes. For more information about
this change, see the entry Input
Validation vs. Model Validation in
ASP.NET MVC on Brad Wilson’s blog.
For the more complex cases I moved away from simple DataAnnotations to the following: Validation with visitors and extension methods.
If you want to make use of your DataAnnotations you would replace something like the following:
public IEnumerable<ErrorInfo> BrokenRules (Payment payment)
{
// snip...
if (string.IsNullOrEmpty (payment.CCName))
{
yield return new ErrorInfo ("CCName", "Credit card name is required");
}
}
with a method to validate a property by name via DataAnnotations (which I don't have atm).
I created a partial model binder that only validates the keys that were submitted. For security reasons (if I was going to take this a step farther) I'd create a data annotation attribute that marks which fields are allowed to be excluded from a model. Then, OnModelUpdated check field attributes to ensure there is no undesired underposting going on.
public class PartialModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
// default model binding to get errors
base.OnModelUpdated(controllerContext, bindingContext);
// remove errors from filds not posted
// TODO: include request files
var postedKeys = controllerContext.HttpContext.Request.Form.AllKeys;
var unpostedKeysWithErrors = bindingContext.ModelState
.Where(i => !postedKeys.Contains(i.Key))
.Select(i=> i.Key).ToList();
foreach (var key in unpostedKeysWithErrors)
{
bindingContext.ModelState.Remove(key);
}
}
}
This isn't related to DataAnnotations but have you looked at the Fluent Validation project? It gives you fine grain control over your validation and if you have object-to-object validation an aggregate object of the two objects will get you going.
Also it seems to have been build with MVC in mind but it also has its own "runtime" so that you can use it in other .NET applications as well which is another bonus in my book.
Related: What’s the best way to implement field validation using ASP.NET MVC?
Let's suppose a solution with the following projects:
Foo; // the MVC web project
Foo.Models;
Foo.Repositories;
Foo.Services;
Foo.Models is the domain of the application with all the entities, doesn't matter if using EF, NH, POCO or whatever. Here's an example:
public class User
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
In Foo.Repositories there is a UserRepository and in Foo.Services there is a UserService.
In the web application let's consider a model binder like following:
public class UserBinder : DefaultModelBinder
{
//...
}
I see three different options on where to put the validation:
In Foo.Models like the following:
public class User
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public ICollection<KeyValuePair<string, string>> ValidateErrors()
{
//Validate if Username, Email and Password has been passed
}
}
In Foo.Services like:
public class UserService
{
public ICollection<KeyValuePair<string, string>> ValidateErrors()
{
//Validate if Username, Email and Password has been passed
}
}
In Foo inside the model binder:
public class UserBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var user = (User)bindingContext.Model;
// validate everything here
base.OnModelUpdated(controllerContext, bindingContext);
}
}
Another thing to notice is that considering the first 2 options [Model and Service] there is another decision to make: ValidateErrors method can be called directly on the controller or inside the Binder.
I have 2 questions on the scenario:
Should the validation be:
In the Model being called from the controller?
In the Model being called from the binder?
In the Service being called from the controller?
In the Service being called from the binder?
Directly in the Binder?
Any other idea?
All the above scenario discuss about the User creation. But what about User logon?
Let's say user uses the username and password to login in the application, so it won't need to validate the e-mail.
Where this validation should be?
In the Model being called from the controller?
In the Service being called from the controller?
Any other idea?
Check out the ASP.NET MVC Contact Manager Sample Application it has a very good architecture im my opinion
http://www.asp.net/learn/mvc/tutorial-26-cs.aspx'>http://www.asp.net/learn/mvc/tutorial-26-cs.aspx
I'm a big fan of putting calling the validation from the controllers and having the validation routine return an ActionResult so the controller can know what to do with the result.
For what it's worth, here's what I have scrounged up in my current project:
I have Models, Repositories (you can call them Services if you like), and ViewModels. I try to avoid writing custom model binders because (a) it's boring and (b) a strange place to put validation, IMHO. To me, a model binder is just taking items from the request and shoving them into an object. PHP, for example, doesn't do any validation when plucking items from a header into the $_POST array; it's the thing we plug the array into that cares about its contents.
My Model objects generally never allow themselves to enter an invalid state. This means that required parameters are passed in during constructors and properties will throw exceptions if they're attempted to be set with invalid values. And, in general, I try to design my Model objects to be immutable. For example, I have an Address object for mailing addresses that is constructed with an AddressBuilder object with looks at the field requirements for a given country by inspecting an AddressScheme that can be retrieved from the AddressSchemeRepository. Phew. But I think it's a good example because it takes something conceptually simple ("validate a mailing address") and makes it complicated in real world usage ("we accept addresses from over 30 countries, and those formatting rules are sitting in a database, not in my code").
Since constructing this Model object is kind of a pain--as well it should be, since it's being quite particular about the data that gets loaded into it--I have a, say, InputAddressViewModel object that my view binds to. The InputAddressViewModel implements IDataErrorInfo so that I get ASP.NET MVC's DefaultModelBinder to add errors to the ModelState automatically. For simple validation routines that I know ahead of time (phone number formatting, first name required, e-mail address format), I can implement these right in the InputAddressViewModel.
The other advantage of having a view model is that because it is shamelessly tailored to a particular view, your real model is more reusable because it doesn't have to make any weird concessions to make it suitable for UI display (e.g., needs to implement INotifyPropertyChanged or Serializable or any of that mess).
Other validation errors about the address I won't know about until I interact with my AddressScheme in my actual Model. Those errors will be there controller's job of orchestrating into the ModelState. Something like:
public ActionResult InputAddress(InputAddressViewModel model)
{
if (ModelState.IsValid)
{
// "Front-line" validation passed; let's execute the save operation
// in the our view model
var result = model.Execute();
// The view model returns a status code to help the
// controller decide where to redirect the user next
switch (result.Status)
{
case InputAddressViewModelExecuteResult.Saved:
return RedirectToAction("my-work-is-done-here");
case InputAddressViewModelExecuteResult.UserCorrectableError:
// Something went wrong after we interacted with the
// datastore, like a bogus Canadian postal code or
// something. Our view model will have updated the
// Error property, but we need to call TryUpdateModel()
// to get these new errors to get added to
// the ModelState, since they were just added and the
// model binder ran before this method even got called.
TryUpdateModel(model);
break;
}
// Redisplay the input form to the user, using that nifty
// Html.ValidationMessage to convey model state errors
return View(model);
}
}
The switch may seem repulsive, but I think it makes sense: the view model is just a plain old class and doesn't have any knowledge of the Request or the HttpContext. This makes the logic of the view model easy to test in isolation without resorting to mocking and leaves the controller code left to, well, control by interpreting the model's result in a manner that makes sense on a Web site--it could redirect, it could set cookies, etc.
And the InputAddressViewModel's Execute() methods looks something like (some people would insist on putting this code into a Service object that the controller would call, but to me the view model will do so much finagling of the data to make it fit the real model that it makes sense to put it here):
public InputAddressViewModelExecuteResult Execute()
{
InputAddressViewModelExecuteResult result;
if (this.errors.Count > 0)
{
throw new InvalidOperationException(
"Don't call me when I have errors");
}
// This is just my abstraction for clearly demarcating when
// I have an open connection to a highly contentious resource,
// like a database connection or a network share
using (ConnectionScope cs = new ConnectionScope())
{
var scheme = new AddressSchemeRepository().Load(this.Country);
var builder = new AddressBuilder(scheme)
.WithCityAs(this.City)
.WithStateOrProvinceAs(this.StateOrProvince);
if (!builder.CanBuild())
{
this.errors.Add("Blah", builder.Error);
result = new InputAddressViewModelExecuteResult()
{
Status = InputAddressViewModelExecuteStatus
.UserCorrectableError
};
}
else
{
var address = builder.Build();
// save the address or something...
result = new InputAddressViewModelExecuteResult()
{
Status = InputAddressViewModelExecuteStatus.Success,
Address = address
};
}
}
return result;
}
Does this make sense? Is it a best practice? I have no idea; it's certainly verbose; it's what I just came up with in the past two weeks after thinking about this problem. I think you're going to have some duplication of validation--your UI can't be a complete imbecile and not know what fields are required or not before submitting them to your model/repositories/services/whatever--otherwise the form could simply generate itself.
I should add that the impetus for this is that I've always kind of detested the Microsoft mentality of "set one property -> validate one property" because nothing ever works like that in reality. And you always end up getting an invalid object persisted because someone forgot to call IsValid or some such on the way to the data store. So another reason for having a view model is that it tailors itself to this concession so we get a lot of CRUD work of pulling items from the request, validation errors in the model state, etc quite easily without having to compromise the integrity of our model itself. If I have an Address object in hand, I know it's good. If I have an InputAddressViewModel object in hand, I know I need to call it's Execute() method to get that golden Address object.
I'll look forward to reading some of the other answers.
After a lot of research I think I got the answers to my question so i decided to share.
The validation code should be on Model.
As per the idea of "thin controller, fat model" AND considering that a model would know what it needs to validate or not.
For example, let's say I decide to user the Foo.Models in other solution but I decide NOT to use any other project and the validation is in other project.
I'll have to re-code the entire validation in this case what is a total waste of time, right?
OK. The validation code must be in the model but where should it be called?
This validation must be called where you're saving it to your database or file.
As in the proposed scenario I'm considering the repository as a domain, then we should consider putting the validation just before the change saving [in this example I'm using Entity Framework but it's not necessary, it's just to show]:
public class UserRepository : IRepository<User>
{
public void Create(User user)
{
user.Validate();
var db = dbFooEntities();
db.AddToUsers(user);
db.SaveChanges();
}
}
As per MS recommendation, the model validation should raise an exception and the controller must populate the ModelState with the errors found [I'll try to update this answer with a sample code on that as soon as I finish my app].
With that we have an answer for question #1.
What about question #2, regarding the login validation?
As login is not a situation where you're persisting your data, the validation should stay on the Service since logging in is a service in this case.
So, the answers for the question are:
In the Model being called from the REPOSITORY [that is called by the controller]
In the Service being called from the controller
This is very interesting and it helps me a lot in deciding where to put validation.
currently I feel the most for each model implementing a "Validate" method, which is called from a Repository or a Service.
However, what about validating if a chosen username is unique?
Should that code be inside the User model, or inside the UserService class, or in the UserRepository class?
If the uniqueness validation should be inside the User model, then the User model should have access to either the UserService or the UserRepository class. Is that OK, or is that against any "best practice" pattern?
For example:
class User
{
string Username { get; set; }
string Email { get; set; }
string Password { get; set; } // hashed and salted of course :)
IEnumerable<RuleViolation> Validate()
{
List<RuleViolation> violations = new List<RuleViolation>();
IUserService service = MyApplicationService.UserService; // MyApplicationService is a singleton class, especialy designed so that the User model can access application services
// Username is required
if ( string.IsNullOrEmpty(Username) )
violations.Add(new RuleViolation("Username", "Username is required"));
// Username must be unique: Should uniqueness be validated here?
else if( !service.IsUsernameAvailable(Username)
violations.Add(new RuleViolation("Username", "Username is already taken!"));
// Validate email etc...
return violations;
}
}
interface IUserRepository
{
void Save(User item);
}
interface IUserService
{
IUserRepository UserRepository { get; }
void Save(User item);
}
class UserService : IUserService
{
public UserService(IUserRepository userRepository)
{
this.UserRepository = userRepository;
}
IUserRepository UserRepository { get; private set}
public void Save(User user)
{
IEnumerable<RuleViolation> violations = user.Validate();
if(violations.Count() > 0)
throw new RuleViolationException(violations); // this will be catched by the Controller, which will copy the violations to the ModelState errors collection. But the question is, should we validat the user here, or in the UserRepository class?
UserRepository.Save(user);
}
}
class UserRepository : IUserRepository
{
void Save(User item)
{
IEnumerable<RuleViolation> violations = user.Validate();
if(violations.Count() > 0)
throw new RuleViolationException(violations); // this will be catched by the Controller, which will copy the violations to the ModelState errors collection. But the question is, should we validate the user here, or in the UserService class?
UserRepository.Save(user);
}
}
My guess would be that validation should be as close to the model as possible. So I'd say that the UserRepository should be the one responsible for validating it's model being added.
The most important queston for me is: Should the User model know about the IUserService / IUserRepository interfaces so that it can validate the Username uniqueness?
Or should the IUserService service validate uniqueness?
I'm curious about your views on this!
I'm using the DataAnnotations attributes in combination with a MVC model binder to do my validation and its pretty awesome. Since I treat User input as Command View Models its the cleanest way to keep domain clean from outside concerns.
http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html
This also allows me to take advantage of AutoForm by LosTechies.com:
http://www.lostechies.com/blogs/hex/archive/2009/06/17/opinionated-input-builders-part-8-the-auto-form.aspx
And I expect the client side validation tools in MVC 2, VS 2010 to take advantage of these attributes as well.
So I'm whipping out user input view models, commands, at a furious pace right now and tying them into not only the AutoForm functionality but my own custom UI templates to get AutoGrid and AutoOutput from these attributes as well.
Nothing is better than saying:
Html.AutoForm(Model);
Or
Html.AutoGrid(Model.Products);
And getting validation and html generation in a very DRY and orthogonal way. My controllers are light, my domain pristine, and my time is unoccupied by writing the same if( string.IsNullOrEmpty() ) method on every object with a FirstName property.
For me the approach was not as "philosophical" as others have written about. I'm trying to be very pragmatic about MVC development and I get a ton of bang for the buck out of these bits.