Asp.Net MVC2 TekPub Starter Site methodology question - asp.net-mvc

Ok I've just ran into this and I was only supposed to be checking my emails however I've ended up watching this (and not far off subscribing to TekPub).
http://tekpub.com/production/starter
Now this app is a great starting point, but it raises one issue for me and the development process I've been shown to follow (rightly or wrongly). There is no conversion from the LinqToSql object when passing data to the view. Are there any negitives to this?
The main one I can see is with validation, does this cause issues when using MVC's built in validation as this is somthing we use extensivly. Because we are using the built in objects generated by LinqToSql how would one go about adding validation, like
[Required(ErrorMessage="Name is Required")]
public string Name {get;set;}
Interested to understand the benifits of this methodology and any negitives that, should we take it on, experiance through the development process.
Should this be taken as a guide and we should be using ViewModels? If so should we always use them even in simple cases? And how/where in the application logic does the Entity get converted to a ViewModel?

With entity objects, you could use buddy classes, whereby you create a second class which acts as a metadata provider for your entity. For instance, with a Customer entity generated by Linq-to-Sql, I could create a buddy class like so:
[MetadataType(typeof(CustomerMeta))]
partial class Customer {
}
public class CustomerMeta {
[DisplayName("Forename", Required(ErrorMessage = "Forename is required.")]
public string Forename { get; set;}
}
Entities are generated as partial classes so you can add your own code to them.
Alternatively, you could forego pushing your entity types to your views and create specific models based around the functionality required, for instance I would typically have a User entity, but when I need to create a User, I have something called a CreateUserSpec model:
public class CreateUserSpec
{
[DisplayName("Forename")]
public string Forename { get; set; }
}
Which has a subset of the properties of the User, only those required to create a User. This is the model I would pass to my view, and repopulate from the form data. For instance:
public class AccountController
{
public ActionResult Register() {
return View(new CreateUserSpec());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(CreateUserSpec spec) {
if (!ModelState.IsValid) {
return View(spec);
}
var user = UserFactory.CreateUser(spec);
// Redirect to authorisation page?
}
}

Related

EF, MVC, Model binding, and Navigation properties

I'm using EF5 Code First with :
public class Scenario
{
public int Id { get; set; }
public IList<Client> Clients { get; set; }
}
public class Client
{
public int Id { get; set; }
public string Name {get;set;}
public int VisibilityNumber{ get; set; }
}
I'm directly sending the scenario object to the view (MVC4, without using a viewmodel class - maybe a mistake ?, but a lot less plumbing code). In my view, I use HiddenFor for Scenario.Id, and a for loop to display an EditFor for each client VisibilityNumber.
This is the Controller :
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
if (ModelState.IsValid)
{
Scenario scen=GetScenarioFromDB(id);
TryUpdateModel(scen,formValues);
if (ModelState.IsValid)
SaveToDb(scen);
}
}
After the TryUpdateModel, for each Clients object (which were correctly loaded from DB) :
VisibilityNumber is correctly set
Id is set to 0, which of course is a bad thing
Name is set to null
After looking at the MVC Source code (DefaultModelBinder/UpdateCollection), I can see that when binding to collections, new items are always created.
If I can't fix that, I think I'm going to use a viewModel, and AutoMapper. I assume that the MVC team wanted to force us to use viewModel, rather than directly send EF object.
You should not get scenario from database in your update. Instead, you should take your bound model, attach it (if edited) or add it (if new) to context and then save changes. It's a common scenario called "disconnected entities" (which you, in fact, do have, because you have model that was disconnected when sent to client, and then got back also disconnected).
I "fixed" DefaultModelBinder/UpdateCollection so that it can work with my use case : when the binding is drilling down in the navigation properties, it uses the current object as model (it's easy, since I'm only doing modifications, no insert or delete) : I can take the DefaultModel source code, put my fix in it, and use it as a custom model binder. It's fun, but a bit dirty and over the top.
But I believe the best way is to use a specific ViewModel, using only the properties which are editable, and use AutoMap to map it to my EF hierarchy. BUT : it has the same problem of creating child objects collection.
In the end, I just did some manual mapping for between my View Model and my EF hierarchy : I'm nearly sure I can do something automatic, which could detect if a child item has been modified or inserted or deleted (since every item has a [key] property, but I just don't have the time budget to implement it.

T4 Self Tracking Entities And Model Validation

I'm using EF4.x Self Tracking Entities in my project and am trying to achieve Model Validation in my MVC4 web application, however, my Model State always seems to be Valid. I'm using T4 templates to generate my "buddy" classes. Below is an example of one of the STE's and its buddy:
STE - generated using T4:
[DataContract(IsReference = true)]
[KnownType(typeof(Filing))]
public partial class FilingHistory: IObjectWithChangeTracker, INotifyPropertyChanged
{
public int FilingHistoryId
{
//Snipped for Brevity
}
// Navigation, ChangeTracking, Association Fix up snipped
}
Here is the Buddy Class generated also via a T4 template I wrote:
[MetadataType(typeof(FilingHistoryMetaData))]
public partial class FilingHistory
{
// Partial Class
}
public class FilingHistoryMetaData
{
[Display(Name = "Filing History Id")]
[Required(ErrorMessage = "Filing History Id is Required.")]
int FilingHistoryId { get; set; }
// Other properties snipped for Brevity
}
I'm going to exclude the key's from each MetaData class because those will be created automatically (just as an fyi). Also, the namespaces for the STE, the empty partial and the buddy class are identical
When I create a simple controller in MVC4 just to test it out, with a Create Template, on the HttpPost Action of Create I have some code as shown below:
[HttpPost]
public ActionResult Create(FilingHistory filingHistoryToCreate)
{
if (ModelState.IsValid) // THIS IS ALWAYS TRUE! even if i pass nothing<----
{
return Redirect("/");
}
return View(filingHistoryToCreate);
}
I read through a bunch of SO links and even went through MSDN, and I think I have everything setup correctly, i.e. namespaces are fine so there is no naked partial class stuff going on.
When my view renders I leave all the textboxes empty, I set a breakpoint to inspect by entity and nothing has been set, yet the model is valid. I also tested by entering some garbage into the textboxes to ensure the model binding was working fine, and it was...
I tried also testing using a console application, and I found out that you have to take an additional step of registering the MetaData type, but I beleive in MVC this isnt required. In case it helps anyone - the console app and registering meta data type didn't work for me either, so I'm thinking my buddy class may be the culprit?
It seems the DataAnnotationsModelMetadataProvider is looking for the public properties when checks for the attributes.
Change your FilingHistoryId to public and it should work:
public class FilingHistoryMetaData
{
[Display(Name = "Filing History Id")]
[Required(ErrorMessage = "Filing History Id is Required.")]
public int FilingHistoryId { get; set; }
// Other properties snipped for Brevity
}

How do I use my own Model classes in conjunction with EF entity classes in MVC?

So I am new to MVC and am working now with MVC3 and the Entity Framework. I am currently using a Model/Schema 1st approach as the database already exists. Therefore I create my ADO.NET Entity Data Model (.edmx) and I have all the needed entities in my MVC app. So far so good on all this.
However let's say one of my Entities is a 'Customer' entity. I can see the auto-generated partial class inheriting from EntityObject in MyEntites.Designer.cs. At this point I want to add some custom business logic to my MVC Model. Natuarally I believe the answer is to use my own partial class created in the Model named 'Customer' as well.
I did a lot of searching on this before asking the question and see all kinds of information on POCO, T4 templates, modifying auto-generated code, etc and am lost. Is it a royal pain to add my own business logic and custom code to the auto-generated entities from EF? I certainly don't want to modify the auto generated code over and over.
I need a straight forward explanation to make the proverbial 'light bulb' go on, and then I can take-off from there. Can someone help me answer how to do this please?
Thanks!
Keep your own class code in a different file, but use the same class and namespace. This will help avoid your code being overwritten by the T4 code generator.
Extending Entity Framework Generated Types
You can also add attributes to generated classes by using a meta class:
Adding Attributes to Generated Classes
Those codes are auto-generated and will be over written on each model update or change.
You can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...

Where do you put your validation in asp.net mvc 3?

One common recommended practice in asp.net mvc is that you should not send your business models to your views.. instead you should create viewmodels specific to each view.
When that is done and you call the ModelState.IsValid method in your controller you are effectively checking the validity of the viewmodel but not the business object.
What is the conventional approach to dealing with this?
public class Person
{
public int ID {get; set;};
[Required]
public string Name {get; set;}
[Required]
public string LastName {get; set;}
public virtual ICollection<Exam> Exams {get; set;}
}
public class PersonFormViewModel
{
public int ID {get; set;};
[Required]
public string Name {get; set;}
[Required]
public string LastName {get; set;}
}
This is exactly what I have right now but Im not sure if the [Required] attribute should appear on both models or just the ViewModel or just the Business Model.
Any tips on this issue are appreciatedd.
More links to support my claim that it is a common good practice to always use view models.
How to add validation to my POCO(template) classes
http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx
My preference is to do input validation on the view models, and business validation on the domain models.
In other words, any data annotations such as required fields, length validation, regex, etc should be done on your view models, and added to the model state when error occurs.
And you'll probably have business/domain rules that rely on more than just a "form", so you should do that either in the domain models (execute the validation after they're mapped back), or with a service layer.
All our models have a method called "Validate", which we call in the services prior to persisting. They throw custom exceptions if they fail business validation, which gets caught by the controller and also added to the model state.
May not be everyone's cup of tea, but it's consistent.
Example of business validation, as requested:
Here's an example of a domain model we have, which represents a generic "Post" (question, photo, video, etc):
public abstract class Post
{
// .. fields, properties, domain logic, etc
public void Validate()
{
if (!this.GeospatialIdentity.IsValidForThisTypeOfPost())
throw new DomainException(this, BusinessException.PostNotValidForThisSpatial.);
}
}
You see there, I am checking against business rules, and throwing custom exceptions. DomainException is our base, and we have many derived implementations. We have an enum called BusinessException, which contains values for all our exceptions. We use extension methods on the enum to provide the resource-based error message.
This is not simply a field on the model I'm checking, e.g "All posts must have a subject", because although that is part of the domain, it's input validation first and foremost, and thus is handled via the data annotations on the view model.
Now, the controller:
[HttpPost]
public ActionResult Create(QuestionViewModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
try
{
// Map to ViewModel
var model = Mapper.Map<QuestionViewModel,Question>(viewModel);
// Save.
postService.Save(model); // generic Save method, constraint: "where TPost: Post, new()".
// Commit.
unitOfWork.Commit();
// P-R-G
return RedirectToAction("Index", new { id = model.PostId });
}
catch (Exception exc)
{
var typedExc = exc as DomainException;
if (typedExc != null)
{
// Internationalised, user-friendly domain exception, so we can show
ModelState.AddModelError("Error", typedExc.BusinessError.ToDescription());
}
else
{
// Could be anything, e.g database exception - so show generic msg.
ModelState.AddModelError("Error", "Sorry, an error occured saving the Post. Support has been notified. Please try again later.");
}
}
return View(viewModel);
}
So, by the time we get to the "Save" method on the service, the model has passed input validation. Then the Save method calls post.Validate(), invoking business rules.
If an exception is raised, the controller catches it and displays the message. If it gets pass the Save method and another error occurs (90% of the time, it's Entity Framework, for example), we show a generic error message.
As I said, not for everyone, but this works well for our team. We have a clear separation of presentation and domain validation, and a consistent flow of control from the raw HTTP POST, to the redirect after success.
The MetaData "buddy" class is exactly what this is for. The validation is created once but can be used on both the model and the viewmodel classes:
public class PersonMetaData
{
[Required]
public string Name {get; set;}
[Required]
public string LastName {get; set;}
}
[MetadataType(typeof(PersonMetaData))]
public class Person
{
public string Name {get; set;}
public string LastName {get; set;}
}
[MetadataType(typeof(PersonMetaData))]
public class PersonFormViewModel
{
public string Name {get; set;}
public string LastName {get; set;}
}
Great answer by RPM1984, and nice code sample.
My view is still that using Variant 2 from the start is a pragmatic balance between productivity and structure, but you always have to be willing to move to Variant 3 in some cases, so I advocate a mix of the two approaches where logical. Patterns & Practices however recommend always doing Variant 3 as it is the ideal separation of concerns etc, and it avoids you using two approaches in the same solution which some people don't like and many customers I work with pick Variant 3 and run with that for all models.
I think the key is what RPM1984 said - reusing your business entities inside your View Models is useful for the sake of reusing the validation, but do bear in mind that often your business logic needs to do different validation too (e.g. checking the record doesn't already exist). If you use Variant 3 it empowers you to focus your View Model validation purely on the needs of your views (at the expense of a little extra effort) but you will always need some kind of business logic validation too.
Given that you always pass viewmodels to your view and your domain models are not exposed to the end user through views then i don't see any need for validating domain model itself. For example if you receive PersonViewModel from view through form post you will transform it to Person Model (perhaps through automapper etc.) only if PersonViewModel is valid itself. So i believe that input validations should stay with the view models because they are the one that are bound to input.
Typically your ViewModel will contain a reference to your Model - a ViewModel is only necessary if you need to display additional information in your view that isn't available in your Model, there is no need to replicate the data already present.

Where should be the validation in a ASP.Net MVC scenario having Repository, Service Layer and using Model Binder?

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.

Resources