asp.net mvc database interaction validation - asp.net-mvc

Does anybody have any links or advice on how to hook up validation that requires interacting with the database before updating or adding to the database? Every example I see shows how to validate properties e.g. "Is Required", "Is Email", "Is Numeric", etc, but how do you hook up validation for "Can't order out of stock item"? This xVal blog post touches on it but doesn't provide an example.
I've been following the NerdDinner tutorial which uses a Repository, but this is the bit I don't quite get... Say we had an OrderController with a Create method, and before creating an order we had to first check that the item is in stock. In the NerdDinner style the Controller uses the Repository to talk to the database, so how would our Order object (Model) be able to enforce this validation along with the property validation, as it can't talk to the database?
Thanks for any help

In the NerdDinner tutorial, you can checkout the IsVaild and then the GetRuleViolation methods. Based on your business and database rules, you could use these to check the data you have before you insert it. You could even create an IsValidForInsert Method to check any insert specific rules you need to enforce.
In NerdDinner, the GetRuleViolation allows you to retrieve the violated rules and bubble them up to the interface as you choose.
public bool IsValid
{
get { return (GetRuleViolations().Count() == 0); }
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
if (CheckDbForViolation)
yield return new RuleViolation("Database Violation", "SomeField");
if (String.IsNullOrEmpty(Title))
yield return new RuleViolation("Title is required", "Title");
if (String.IsNullOrEmpty(Description))
yield return new RuleViolation("Description is required", "Description");
if (String.IsNullOrEmpty(HostedBy))
yield return new RuleViolation("HostedBy is required", "HostedBy");
... etc ...
yield break;
}
public bool CheckDbForViolation()
{
/// Do your database work here...
}
You could take this further and split database code into the repository. The CheckDbForViolation would call the repo for the info and then determine if there was a violation or not. In fact if you are using a repository, I think that would be the preferable way of doing it.

You do not really need any guidance from examples on how to do this. Ultimately you will have to be able to create such applications on your own which means being creative.
I've decided from the beginning do not use either built-in validation or membership API in order not to run into its limitations at some point of time.
For your situation: it's pretty much standard.
Imagine the execution flow as follows:
Post form
Validate input data format without talking to the database
If (2) is pass, then you validate the input from the point of business rules/data integrity. Here you talk to the database
If (3) passed then perform your operation whatever it is. If it somehow fails (maybe data integrity rules in the database prohibit the operation, say, you deleted a related object from the other browser window) then cancel it and notify the user of an operation error.
Try to keep controller methods as empty as possible. The validation and operation logic should reside in your models and business logic. The controller should basically attempt the one intended operation and based on the status returned just return one view or the other. Maybe a few more options, but not the whole load of checks for user roles, access rights, calling some web services etc. Keep it simple.
P.S. I sometimes get the impression that the built-in features intended to simplify simple things for majority of developers tend to create new barriers over the removed ones.

I would create an OrderService with a method PlaceOrder(Order order). The OrderService use the Repository to perform CRUD ops and to enforce business rules (stock check) and eventually thrown exception on rules violation you can catch and report to the user.

Related

How can I access lookup data via an injected service from within an entity?

My application is using DDD with .NET Core and EF Core. I have some business rules that run within an entity that need to check dates against a cached list of company holiday dates. The company holidays are loaded from the db and cached by an application service that is configured with our DI container so it can be injected into our controllers, etc.
I cannot determine how, or if it's the right/best approach, to get the service injected into the entity so it can grab those dates when running business rules. I did find this answer that appears to demonstrate one way to do it, but I wanted to see if there were any additional options because that way has a bit of a code-smell to me upon first glance (adding a property to the DbContext to grab off the private constructor injected context).
Are there any other ways to accomplish something like this?
ORM classes are very rarely your domain objects. If you can start with your domain and seamlessly map to an ORM without the need for infrastructure specific alterations or attributes then that is fine; else you need to split your domain objects from your ORM objects.
You should not inject any services or repositories into aggregates. Aggregates should focus on the command/transactional side of the solution and work with pre-loaded state and should avoid requesting additional state through any handed mechanisms. The state should be obtained and handed to the aggregate.
In your specific scenario I would suggest loading your BusinessCalendar and then hand it to your aggregate when performing some function, e.g.:
public class TheAggregate
{
public bool AttemptRegistration(BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(DateTime.Now))
{
return false;
}
// ... registration code
return true;
}
// or perhaps...
public void Register(DateTime registrationDate, BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(registrationDate))
{
throw new InvalidOperationException();
}
// ... registration code
}
}
Another take on this is to have your domain ignore this bit and place the burden on the calling code. In this way if you ask you domain to do something it will do so since, perhaps, a registration on a non-working day (in my trivial example) may be performed in some circumstances. In these cases the application layer is responsible for checking the calendar for "normal" registration or overriding the default behaviour in some circumstances. This is the same approach one would take for authorisation. The application layer is responsible for authorisation and the domain should not care about that. If you can call the domain code then you have been authorised to do so.

breeze: Tracking errors with many-to-many associations

A few weeks ago, I've asked how to save Many-To-Many associations with breeze.
Ward Bell came up with this nice solution: breeze: many-to-many issues when saving
I've implemented his solution and it works really well. One issue I've come up with recently though, is how to track errors ?
Taking Ward's example, we manipulate UserRoleVm instances. Therefore validationErrorsChanged will not be triggered for this property.
How could I use breeze to raise an error if say, the parent entity does not have at least one UserRoleVm entity in its collection ?
The UserRoleVm is a regular JavaScript object. It is not a Breeze entity and so does not participate in the Breeze validation support. There is no obvious way to make it do so (at least not obvious to me). Almost anything I can dream up would be more complicated than writing traditional, view-based validation.
What kind of validation do you need? In the example that I put together, the user can only add and remove roles (the equivalent of super powers). There is no way the user can touch any value of the corresponding mapping entity (which may not even exist yet).
When I turn my imagination loose, I speculate about the rules governing how many roles the user can have or whether certain combinations of rule are allowed ... or disallowed. Is that what you mean?
If I had such rules, I'd build validation logic into the outer ViewVM (not the UserRoleVMs) ... the VM that supervises the user's actions. This logic would be quite apart from the Breeze validation logic that you register in metadata ... the validation rules implemented by Breeze inside each entity's EntityAspect.
Ultimately, I would have Breeze validations too ... probably entity validations on the parent User entity type ... so that I could guard against an actual attempt to save an invalid UserRole combination.
But such Breeze validation rules wouldn't kick in until you tried to save. While the user is working with "item VMs" (the UserRoleVms), the validation rules would be defined and implemented separately by the ViewVM in good old vanilla JavaScript.
Such is my thinking at the moment.
Following Ward's advice, I have:
-added the following code for forcing User entity's state to be modified whenever a UserRoleVM is added or removed:
$scope.user.entityAspect.setModified();
-added a custom validator for validating the UserRoles collection on the User entity:
function notEmptyCollectionValidator() {
var name = "notEmptyCollectionValidator";
var validator = new breeze.Validator(name, function (value) {
if (!value || value.length === 0) {
return false;
} else {
return true;
}
});
return validator;
}
breeze.Validator.registerFactory(notEmptyCollectionValidator, 'notEmptyCollectionValidator');
var entityType = metadataStore.getEntityType('User');
entityType.getProperty('userRoles').validators.push(breeze.config.functionRegistry['Validator.notEmptyCollectionValidator']());
Now when I hit the save button, the validation occurs on the userRoles collection. If no userRole was selected, I get a validation error and I show a * next to the control in th UI.
Obviously, that does not work for OnChange validation. I don't know yet how I'm going to achieve that.

MVC FluentValidation with entity framework in separate .dll

I have a separate .dll with our database model and partial classes etc in using FluentValidation which works fine (it's to be used by both by desktop barcoding terminals and also by our website).
For the desktop apps I can read and display all errors like below
public override int SaveChanges()
{
var errors = this.GetValidationErrors();
if (errors.Any())
{
//handle validation errors
return 0;
}
else
{
return base.SaveChanges();
}
}
For the MVC site I can set up validators on individual models or create data annotations and get those working okay (which is not what I want). The thing I can't get my head around is how I can force my models to map to my entities in a way that I can display the fluent validation messages in the views. I don't want to have two separate sets of logic to be maintained and the barcoding apps and website must use the same.
Do I have to map my entities directly to the views? which i've been led to believe is a bad thing and not very flexible. Or is there a way of stating that a field in a model maps back to an attribute of one of my entities? perhaps an annotation of some description.
EDIT:
Just some clarification for the types of validation i'll need.
most front end input type validation will still stay in the viewModels (required/length/password matches etc - basically all the stuff I can use for client side validation as well). But there are all the business logic validations that I don't want there. Things like email addresses must be validated before other options can be set, account numbers must be of a particular format based on name (stuff I can't do with a regex). This particular date is not a valid delivery date etc.
I guess one thing I could do is add these to the ValidationSummary somehow and display them separate from the individual fields.
I think you're just looking at the situation wrong. What MVC is all about is a separation of concerns. There's things the database needs to know about that your views could care less, and vice versa. That's why the recommended practice is to use view model with your views and not the entity itself.
Validation is much the same. Something like the fact that a password confirmation needs to match the password the user entered does not concern the database at all. Or more appropriately, something like a validation on minimum amount of characters in the password does not concern the database, either; it will only ever receive a salted and hashed version of the password. Therefore it would be wrong to put this kind of validation on your entity. It belongs on the view model.
When I first started out using MVC, I used to add all the validation logic to my entity class and then go and repeat that same validation on my view model. Over time, I started to realize that very little of the validation actually needs to be on both. In fact, the largest majority of validation will should just go on your view model. It acts as a gatekeeper of sorts; if the data is good enough to get through your view model, it's good enough for your database. The types of validation that make sense on your entity is things like Required, but even that is really only necessary on a nullable field that must have a value by the time it gets to your database. Things like DateTimes are non-nullable by default, and EF is smart enough to make them non-nullable on the tables it creates by default. MaxLength is at times worthwhile if there should be a hard limit on the length of a text field in your database, but more often than not, nvarchars work just fine.
Anyways the point is that if you actually sit down and start evaluating the validation on your entity, you'll likely see that most of it is business logic that only applies to how your application works and not to how the data is represented at the database level. That's the key takeaway: on your entity, you only need the validation that's necessary for the database. And that's generally pretty thin.
Just an update. to get the two tier validation that i needed i had to mark all my entity model classes as IValidatable. Then i overrode the validate method for each class and invoked my fluent validation validator method there, passing back the errors needed. for the modelstate.addmodelerror i set the key as the field name and it mapped back okay. bit more code but it works. if i find a better way to do this ill update.

Advice on POCO Validation with ASP.NET MVC/Entity Framework

Here's the scenario:
ASP.NET MVC2 Web Application
Entity Framework 4 (Pure POCO's, Custom Data Context)
Repository Pattern
Unit of Work Pattern
Dependency Injection
Service Layer mediating Controller -> Repository
So basically, all the cool stuff. :)
Flow of events for a basic UI operation ("Adding a Post"):
Controller calls Add(Post) method on service layer
Service layer calls Add(T) on repository
Repository calls AddObject(T) on custom data context
Controller calls Commit() on Unit of Work
Now, i'm trying to work out where i can put my validation.
At this stage, i need two types of validation:
Simple, independant POCO validation such as "post must have a title". This seems a natural fit for Data Annotations on the POCO's.
Complex business validation, such as "cannot add a comment to a locked post". This can't be done by Data Annotations.
Now, i have been reading "Programming Entity Framework, Second Edition" by Julie Lerman (which is excellent BTW), and have been looking into hooking into the SavingChanges event in order to perform "last-minute" validation. This would be a nice way to ensure validation always happens whenever i do "something" (add, modify, delete), but it's also a little late IMO (as the items are already in the state manager) - so what can i do if validation fails, remove them?
I could of course make my POCO's implement an interface (say "IValidatable"), and call a method on this interface during this event.
But this seems "too late" for business validation - is this the consensus?
I'm basically looking for guidance here, i'm trying to design a re-usable, intelligent validation scheme for complex business logic, given my above architecture.
Another curve-ball for you - as you know, POCO's with EF mean the POCO's have all the properties on the DB - so i might have a "PostID" property, with get/set accessors (as EF needs to get/set these properties).
But the problem is, "PostID" is an identity column, so how do i protect the field from being explicity set? E.g if i (for some reason) do the following:
var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();
This will throw a SqlException. How can i prevent this? I can't "hide" the property (make it private, or even internal) as the POCO's are in a seperate assembly to the Repository.
A note on validation - i'm planning to create custom exceptions (deriving from Exception). So when validation fails, i need to throw these exceptions.
That way, i can code something like this on my controller:
[HttpPost]
public ActionResult AddPost(Post post)
{
try
{
IUnitOfWork uow = new UnitOfWork();
postService.Add(post);
uow.Commit();
}
catch(InvalidPostOperation ipo)
{
// add error to viewmodel
}
}
Will i have to manually do validation on the service layer everytime i do an Add? Then how can i handle Save? (as this is on the Unit of Work, not the service layer).
So to prevent this from being a "all over the place" question, here are my questions:
Simple POCO validation - should this be done with Data Annotations? Pros/cons/gotchas?
Under what circumstances (if any) should we be hooking into the SavingChanges event of the EF Data Context in order to provide validation?
Where should i be performing complex business validation? In the service explicity, or a method on the POCO's (which i can call from service). How can i create an intelligent/reusable scheme?
How can we "hide" auto-generated properties of POCO's from being tampering with?
Any thoughts would be most appreciated.
Apologize if this post is "too long", but it's an important issue and one that can be solved in many ways, so i wanted to provide all the info in order for the best possible answer.
Thanks.
EDIT
The below answer is helpful, but i'm still (ideally) looking for more thoughts. Anyone else?
Well like you said, DataAnnotations is not appropriate for all situations. Cons are mainly complex validation (multiple property and multiple property different object) in my experience.
If i were you, i would leave business/domain validation out of the Data Layer (EF) as much as possible. If there is a Data Layer validation scenario, then fine (eg. validating complex parent/child relationships - this is purely DB stuff).
Yes, the complex business validation should be in the Service Layer or in the Model Objects (attached, via partial classes or some inheritance approach: interfaces/derived classes). There's debate about this between ActiveRecord people, Repository Pattern people and DDD people, but go with what works for you, is simple and will enable rapid deployment and low cost application maintenance. This is a simple example of how you might attach more complex validation to domain objects yet is still compatible with the DataAnnotations interface and thus is 'MVC friendly'.
Good question. -one i have not found a solution i'm 100% happy with yet. I have played with the idea of private setters and it's not great. Have a quick read of this summarized Evans DDD book. It's great quick read and it might provide some insight about the purpose and difference between Model Objects and Value Objects. This is where i think object design will mitigate the problems your having with the property "tampering" (as you call it) but without fixing the property visibility. Ie, another solution might lie elsewhere. Hope this helps.
Hey, probably a bit late but here goes anyway...
It all depends on your architecture, i.e. Is there a logical seperation, in your application: UI, Service Layer, Repository Layer. If you are hooking onto the Save event, how exactly will that be done? From what I observed you would be calling the repository Layer for Persistance only right? However you are hooking onto the save event, giving control back to the Service Layer/ Business Layer whatever then forcing the save through right?
I personally feel the Service layer/ Business Layer should take care of it in completion then say, hey mr repo layer -> save this object.
With regards to validation, Data Annotations should be used with the UI, so simple valiation like [Required] etc, this will be helpful with the Client Side validation but complex business logic or complex validation should be hooked into the service layer/ business layer, that way it is reusable across all entities/ objects/ POCOS etc.
With regards to preventing certain private fields not being tampered with... only allow your service layer/ business layer to actually set the object that will be persisted (yes i mean :) ...) hand coding it, I felt this was the safest option for me anyway, as I will simple do:
var updatedpost = _repo.GetPost(post.postid);
updatedpost.comment = post.comment;
updatedpost.timestamp = datetime.now;
Kind of wasteful but that way your buseinss layer takes control, however this is just my experience I may be wrong, I have read a lot into model binding, validaiton and other stuff however there seemed to be cases where things never work as expected e.g. [Required] attribute (see Brad WIlson's) post.

Reusing validation attributes in custom ViewModels

When I started using xVal for client-side validation, I was only implementing action methods which used domain model objects as a viewmodel or embedded instances of those objects in the viewmodel.
This approach works fine most of the time, but there are cases when the view needs to display and post back only a subset of the model's properties (for example when the user wants to update his password, but not the rest of his profile data).
One (ugly) workaround is to have a hidden input field on the form for each property that is not otherwise present on the form.
Apparently the best practice here is to create a custom viewmodel which only contains properties relevant to the view and populate the viewmodel via Automapper. It's much cleaner since I am only transferring the data relevant to the view, but it's far from perfect since I have to repeat the same validation attributes that are already present on the domain model object.
Ideally I'd like to specify the Domain Model object as a meta class via a MetaData attribute (this is also often referred to as "buddy class"), but that doesn't work since xVal throws when the metadata class has properties that are not present on the viewmodel.
Is there any elegant workaround to this? I've been considering hacking the xVal sourcecode, but perhaps there is some other way I have overlooked so far.
Thanks,
Adrian
Edit: With the arrival of ASP.NET MVC 2, this is not only a problem related to validation attributes anymore, but it also applies to editor and display attributes.
This is the quintessential reason why your input screens should not be tightly coupled to your model. This question actually pops up here on the MVC tag about 3-4 times a month. I'd dupe if I could find the previous question and some of the comment discussion here is interesting. ;)
The issue your having is you're trying to force two different validation contexts of a model into a single model which fails under a large amount of scenarios. The best example is signing up a new user and then having an admin edit a user field later. You need to validate a password on a user object during registration but you won't show the password field to the admin editing the user details.
The choices for getting around these are all sub-optimal. I've worked on this problem for 3 projects now and implementing the following solutions has never been clean and usually frustrating. I'm going to try and be practical and forget all the DDD/db/model/hotnessofthemonth discussions everybody else is having.
1) Multiple View Models
Having viewmodels that are almost the same violates the DRY principal but I feel the costs of this approach are really low. Usually violating DRY amps up maintenance costs but IMHO the costs for this are the lowest and don't amount to much. Hypothetically speaking you don't change how max number characters the LastName field can have very often.
2) Dynamic Metadata
There are hooks in MVC 2 for providing your own metadata for a model. With this approach you could have whatever your using to provide metadata exclude certain fields based on the current HTTPRequest and therefore Action and Controller. I've used this technique to build a database driven permissions system which goes to the DB and tells the a subclass of the DataAnnotationsMetadataProvider to exclude properties based values stored in the database.
This technique is working great atm but the only problem is validating with UpdateModel(). To solve this problem we created a SmartUpdateModel() method which also goes to the database and automatically generates the exclude string[] array so that any non-permissisable fields aren't validated. We of course cached this for performance reasons so its not bad.
Just want to reiterate that we used [ValidationAttributes] on our models and then superceeded them with new rules on runtime. The end result was that the [Required] User.LastName field wasn't validated if the user didn't have permission to access it.
3) Crazy Interface Dynamic Proxy Thing
The last technique I tried to was to use interfaces for ViewModels. The end result was I had a User object that inherited from interfaces like IAdminEdit and IUserRegistration. IAdminEdit and IUserRegistration would both contain DataAnnotation attributes that performed all the context specific validation like a Password property with the interfaces.
This required some hackery and was more an academic exercise than anything else. The problem with 2 and 3 is that UpdateModel and the DataAnnotationsAttribute provider needed to be customized to be made aware of this technique.
My biggest stumbling block was I didn't ever want to send the whole user object to the view so I ended up using dynamic proxies to create runtime instances of IAdminEdit
Now I understand this is a very xVal specific question but all of the roads to dynamic validation like this lead to customization of the internal MVC Metadata providers. Since all the metadata stuff is new nothing is that clean or simple to do at this point. The work you'd have to do to customize MVC's validation behavior isn't hard but requires some in depth knowledge of how all of the internals work.
We moved our validation attributes to the ViewModel layer. In our case, this provided a cleaner separation of concerns anyway, as we were then able to design our domain model such that it couldn't get into an invalid state in the first place. For example, Date might be required on a BillingTransaction object. So we don't want to make it Nullable. But on our ViewModel, we might need to expose Nullable such that we can catch the situation where the user didn't enter a value.
In other cases, you might have validation that is specific per page/form, and you'll want to validate based on the command the user is trying to perform, rather than set a bunch of stuff and ask the domain model, "are you valid for trying to do XYZ", where in doing "ABC" those values are valid.
If ViewModels are hypothetically being forced upon you, then I recommend that they only enforce domain-agnostic requirements. This includes things like "username is required" and "email is formatted properly".
If you duplicate validation from the domain models in the view models, then you have tightly coupled the domain to the UI. When the domain validation changes ("can only apply 2 coupon per week" becomes "can only apply 1 coupon per week"), the UI must be updated. Generally speaking, this would be awful, and detrimental to agility.
If you move the validation from the domain models to the UI, you've essentially gutted your domain and placed the responsibility of validation on the UI. A second UI would have to duplicate all the validation, and you have coupled two separate UI's together. Now if the customer wants a special interface to administrate the inventory from their iPhone, the iPhone project needs to replicate all the validation that is also found in the website UI.
This would be even more awful than validation duplication described above.
Unless you can predict the future and can rule out these possibilities, only validate domain-agnostic requirements.
I don't know how this will play for client-side validation, but if partial validation is your issue you can modify the DataAnnotationsValidationRunner discussed here to take in an IEnumerable<string> list of property names, as follows:
public static class DataAnnotationsValidationRunner
{
public static IEnumerable<ErrorInfo> GetErrors(object instance, IEnumerable<string> fieldsToValidate)
{
return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>().Where(p => fieldsToValidate.Contains(p.Name))
from attribute in prop.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(prop.GetValue(instance))
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
}
}
I'm gonna risk the downvotes and state that there is no benefit to ViewModels (in ASP.NET MVC), especially considering the overhead of creating and maintaining them. If the idea is to decouple from the domain, that is indefensible. A UI decoupled from a domain is not a UI for that domain. The UI must depend on the domain, so you're either going to have your Views/Actions coupled to the domain model, or your ViewModel management logic coupled to the domain model. The architecture argument is thus moot.
If the idea is to prevent users from hacking malicious HTTP POSTs that take advantage of ASP.NET MVC's model binding to mutate fields they shouldn't be allowed to change, then A) the domain should enforce this requirement, and B) the actions should provide whitelists of updateable properties to the model binder.
Unless you're domain is exposing something crazy like a live, in-memory object graph instead of entity copies, ViewModels are wasted effort. So to answer your question, keep domain validation in the domain model.

Resources