Entity Framework 4.1 Server-side validation - asp.net-mvc-3

The data I work with can be added from different interfaces. So in my MVC application I need to validate that the data read from the database is correct according to the rules/attribute I sat in my model. Depending on the validation send the user to different Views.
I need to do this validation on the SERVER-SIDE
var myModelClassObj = myDbContextInheritedModelClass.theDbSetClassMapToModel.Find(123);
// How do i validat this

The DbContext class has a protected ValidateEntity method. You can call that method to validate your entity.
public class myDbContextInheritedModelClass : DbContext
{
public DbEntityValidationResult Validate(object entity)
{
return ValidateEntity(Entry(entity));
}
}
Then
var myModelClassObj = myDbContextInheritedModelClass
.theDbSetClassMapToModel.Find(123);
var validationResult = myDbContextInheritedModelClass.Validate(myModelClassObj);

Related

Injecting Non-User-Submitted Data For Use During Validation

From what I can tell, ASP.Net Core performs model state validation before calling the relevant controller action method. This means that code in the action method isn't given an opportunity to add data to the model before it is validated.
What is the ASP.Net Core way of giving a view model access to additional, non-user-submitted data prior to validation?
Example
What I'm trying to do (doesn't work).
The view model's Validate method expects data to be in ValidOptions. However, since validation occurs before the controller can set this property, validation causes the view model to throw an ArgumentNullException.
// From the Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Process([Bind("SelectedId")]ViewModels.Import details)
{
// data needed for validation
details.ValidOptions = await service.ImportTypes.ToListAsync();
if (ModelState.ValidationState != ModelValidationState.Valid) {
// ...
}
}
// From ViewModels.Import
public IEnumerable<Option> ValidOptions { get; set; }
public int SelectdId {get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// throws ArgumentNullException because ValidOptions hasn't been set when this is executed
var option = ValidOptions.Single(t => t.Id == SelectdId);
//...
}
Probably many ways to skin a cat here. But the easiest for you is probably custom model binders. It's a way to "supplement" or change the binding of your model before it hits the controller. I will say that some see it as extremely bad practice to call an external service/repository at the point of model binding, but it does work and can come in handy.
You need to implement a class that inherits from IModelBinder.
public class MyViewModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
//Bind here. Including calling external services if you want.
}
}
Then you need to implement a provider, this essentially says "when" to bind.
public class MyViewModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType == typeof(MyViewModel))
return new MyViewModelBinder();
return null;
}
}
In your configure method of your startup.cs, you need to add the provider to the ModelBinderProviders list.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc(config =>
config.ModelBinderProviders.Add(new MyViewModelBinderProvider())
);
}
Further Documentation :
http://dotnetcoretutorials.com/2016/12/28/custom-model-binders-asp-net-core/
http://intellitect.com/custom-model-binding-in-asp-net-core-1-0/
I don't think the official documentation has an article on custom model binders yet unfortunately.

Web API 2- Data Annotations Validation-No Duplicates in the Request

I am using WEB API 2.
In my request I pass the request as Collection of Mytype
MyType has following properties:
Id(int),
PaymentId(int).
I need the following validation. Every Id of the request should be Unique.
Do I need to write custom validation or Is there any builtin DataAnnotationValidation exist for that?
The only way I can think of is writing a model class inheriting IValidatableObject or writing a custom validation attribute for the entire model. Web API will validate your model on the custom validation logic.
public class MyModel : IValidatableObject
{
public IEnumerable<MyType> MyTypes { get; set;}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
foreach(var myType in this.MyTypes)
{
// do validation logic
if (error)
{
yield return new ValidationResult("All Ids must be unique!")
}
}
}
}

N-Tier Service Layer Validation Show Business Logic Error in Presentation Layer

I am converting from the old ways of ASP.NET Web Forms to ASP.NET MVC. I have a project that I am working on that has about 40-50 tables in the database. I have decided to use Entity Framework as my data access layer. I have also decided to put a repository layer and unit of work abstraction over EF so that I am not tied to it and so that I can do unit testing. Finally, I want to make my controllers "thin" so I am looking at implementing a business "service" layer for my business logic.
The thing I am struggling with is how do I propagate Business Logic Errors from my service layer to my Presentation UI layer so that an appropriate error can be shown? Please note that I am trying to look for a solution that is NOT MVC specific as this service/business logic layer will likely be used in other things besides an MVC app (console app's, web services, etc.)
On to some code...
Lets say I have a POCO / data / domain model like so:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
// other properties (navigation, etc)...
}
An Entity Framework fluent configuration/mapping class like so:
public class CategoryMap : EntityTypeConfiguration<Category>
{
public CategoryMap()
{
this.HasKey(c => c.Id);
this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // auto increment identity in our DB schema
this.Property(c=> c.Name)
.IsRequired() // defined as NOT NULL in DB schema so we put a constraint here
.HasMaxLength(150); // defined as varchar(150) in DB schema so we put a constraint here
this.Property(c=> c.Description)
.IsRequired(); // defined as NOT NULL in DB schema so we put a constraint here
// fluent config for related entities (navigation properties) would go here...
}
}
A unit of work encapsulating multiple repositories like so:
public class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext context;
private CategoryRepository catRepo;
public UnitOfWork()
{
this.context = new MyDbContext();
}
public ICategoryRepository Categories
{
get { return this.catRepo?? (this.catRepo= new CategoryRepository (this.context)); }
}
}
A service / business logic layer like so:
public class CategoryService : ICategoryService
{
private readonly IUnitOfWork unitOfWork;
public CategoryService(IUnitOfWork uow) // injected by IoC
{
this.unitOfWork = uow;
}
public Category CreateNewCategory(Category category)
{
if (category == null)
{
throw new ArgumentNullException("category cannot be null");
}
// Simple business logic here to make sure another category with this name does not already exist.
int count = this.unitOfWork.Categories.Count(cat => cat.Name == category.Name);
if (count > 0)
{
// *** This is the error I want the user to see in the UI ***
throw new Exception("Sorry - a category with that name already exists!");
}
}
}
And a controller like this:
public ManageCategoriesController : Controller
{
ICategoryService catSvc;
public ManageCategoriesController(ICategoryService svc) // injected by IoC
{
this.catSvc = svc;
}
[HttpPost]
public ActionResult(CategoryCreateModel createModel) // my View Models / Create Models have Data Annotations on them
{
if (ModelState.IsValid)
{
// use of AutoMapper to map from View Model to domain model...
Category cat = Mapper.Map<CategoryCreateModel , Category>(createModel);
this.catSvc.CreateNewCategory(cat); // ***need to get potential errors from Service and display on form.***
return this.RedirectToAction("Index");
}
}
}
First of all, can anybody tell me if I am on the right track with using View Models? I feel like I almost have three View Models (Create, Edit, View/List) per domain model.
Secondly, my EF configuration/mapping class takes care of the database constraints. Some of these constraints (e.g. Max length) are also data annotations in the View Models and can easily be displayed on the UI. But where can I show my custom business logic errors?
First, your overall approach to MVC looks good to me :-)
Second, you most likely want to use DataAnnotation on your view models for model validation. Have a look this blog post for a good intro on using it in ASP.MVC.
In case of custom validation not suitable for data annotation you can do the following in your controller:
try
{
// the following exception could be thown by some nested validation logic
// e.g. while processing a post request
throw new ValidationException("the error description");
}
catch (ValidationException exception)
{
ModelState.AddModelError("", exception.Message);
}
This is a pretty old question, but for future readers I'd like to add something.
If you're actually using a N-Tier pattern, entity validation should be in your Service layer. Not in your MVC Controller.
The right way to do it is to do basic model validations in your model class, using ValidationAttributes, but re-validate your entities in your service layer.
Add a handling of custom exceptions in your controller to catch any validation error raised from the service layer, and display error messages.
If your service layer is just there to call your repositories, you're doing something wrong ;)

Custom Validation in Spring MVC 3.0 - Pass #Model to Validator

I am trying to write a custom validator in a Spring MVC application. I would like to know if there a way to pass the #Model object to a custom spring validator?
Say, I have a Person object and Account object. I have to write a custom validator to validate Person, but the validation is dependent of the Account object and other objects in session.
For example, Person cannot have more than 3 accounts, account types have to be of specific category and not old than 3 years (this value, ie the number years is dynamic based on the profile logged in and is in session).
How can I pass both objects, especially #Model to the validator.
public class ServiceValidator implements Validator {
#Autowired
private ServiceDAO servicesDao;
#Override
public boolean supports(Class<?> clasz) {
return clasz.isAssignableFrom(Person.class);
}
#Override
public void validate(Object obj, Errors errors) {
Person subscriber = (Person) obj;
// How can I access #Model object here ???
}
Doubt if you can but have two workarounds:
a. If it is persisted data that you are looking for, probably it is just better to retrieve it once more in the validator and validate using that data, so for eg, in your case if you are validating person and persons account details are retrievable from DB, then get it from DB and validate in your validator using the retrieved data.
b. Probably this is a better approach if the number of places where you need to use the validator is fairly confined:
public class ServiceValidator {
#Autowired
private ServiceDAO servicesDao;
public void validate(Person subscriber, List<Account> accounts, ..., Errors errors) {
}
Just call the above validator directly from your requestmapped methods..
In your controller..
List<Account> accounts = //retrieve from session
serviceValidator.validate(subscriber, accounts, ...errors);
if (errors.hasErrors())..
else..

How to inject dependencies used for validation in .NET MVC3?

We have quite a few validation methods that need to access repositories / database to do their work. So far we have been using the service locator pattern (albeit sparingly) to accomplish this in custom ValidationAttributes:
public override bool IsValid(object value)
{
// use custom service locator in our app's infrastructure
var repos = DependencyInjector.Current.GetService<IXyzRepository>();
...
}
I know this is :( upon as an anti-pattern, and we would like to use a more correct approach. We use unity, and I read this post that says to use a build-up method. However the link in the accepted answer says that the documentation is outdated (retired content).
The solution does not need to use a validation attribute, I suppose it could use IValidatableObject, however the problem remains: how to inject the dependency into the model. Do we need a custom model binder to do this?
Another solution would be to perform the validation in the controller, where dependency injection is easy. To me this feels cluttered though. I would like the model to be validated by the time it gets to the action method.
Also we sometimes use [RemoteAttribute] to perform some of these validations on the client. Currently those methods construct a viewmodel and delegate validation to the model by using the static Validator.TryValidateObject method.
How have you accomplished validation that requires an injected dependency to do its work, without using the SL anti-pattern?
How have you accomplished validation that requires an injected
dependency to do its work, without using the SL anti-pattern?
I use FluentValidation.NET to perform validation in my applications. It allows me to inject dependencies into my validators. It has a really nice integration with ASP.NET MVC. It also supports automatic client side validation for the standard rules just the same way as data annotations using jquery unobtrusive validate:
NotNull/NotEmpty
Matches (regex)
InclusiveBetween (range)
CreditCard
Email
EqualTo (cross-property equality comparison)
Length
I have never used data annotations to perform validation. They are absolutely useless when you need to handle some more complex validation scenarios where you need to validate dependent properties and even use some service. I put complex in italics in the previous sentence because, I don't think that validating that one of the 2 properties is required is a really complex validation scenario and yet, just checkout the amount of infrastructure crap you have to write in order to implement it using data annotations. Looking at this code you no longer know what you are validating.
Inject your validation into your Model.
Validation Attributes can become awkward to work with when your validation stories become more complex. Yuck!
I like to use Entity Framework with Code First. I have full control of my model at that point. I also use FluentValidation like #Darin Dimitrov and I really like its ease of use and simple syntax.
Here’s how you put it together.
I assume you have assembly with your interfaces or contracts.
This will be the base interface for your models…
using System.ComponentModel;
using FluentValidation.Results;
public interface IAbstractBase : IDataErrorInfo
{
bool IsValid { get; }
ValidationResult SelfValidate();
}
and its counterpart in your business layer looks like this…
using System;
using System.Linq;
using FluentValidation.Results;
using Contracts;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public abstract class AbstractBase : IAbstractBase
{
#region IDataErrorInfo
public abstract ValidationResult SelfValidate();
[NotMapped]
public bool IsValid
{
get
{
return SelfValidate().IsValid;
}
}
[NotMapped]
public string Error
{
get
{
var results = SelfValidate().Errors.Select(s => string.Format("● {0}{1}", s.ErrorMessage, Environment.NewLine)).ToArray();
return string.Join("", results);
}
}
[NotMapped]
public IList<ValidationFailure> Errors
{
get
{
var results = SelfValidate().Errors;
return results;
}
}
[NotMapped]
public string this[string columnName]
{
get
{
var validationResults = SelfValidate();
if (validationResults == null) return string.Empty;
var columnResults = validationResults.Errors.FirstOrDefault(x => string.Compare(x.PropertyName, columnName, true) == 0);
return columnResults != null ? columnResults.ErrorMessage : string.Empty;
}
}
#endregion
}
This is your base class for your models. Make sure you implement the abstract method in your models. It should look like this.
public class MyModel : AbstractBase, IMyModel
{
private AbstractValidator<IMyModelValidator> _myModelValidator;
public MyModel():this(new MyModelValidator()){};
public MyModel(AbstractValidator<IMyModelValidator> myModelValidator){
_myModelValidator = myModelValidator;
};
public int MyModelId { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public override ValidationResult SelfValidate()
{
return _myModelValidator.Validate(this);
}
}
Your validator class will look something like this.
public class MyModelValidator : AbstractValidator<IMyModelValidator>
{
private IMyModelProvider _myModelProvider;
public MyModelValidator(IMyModelProvider myModelProvider){ _myModelProvider = myModelProvider;};
private void SetRules()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Please specify a project name.");
RuleFor(x => x.Name.Length).LessThanOrEqualTo(100).WithMessage("The project name must be less than or equal to 100 characters.");
}
public override ValidationResult Validate(IMyModel instance)
{
SetRules();
return base.Validate(instance);
}
}
Pass your validation results from your Model to your view in your Controller using the following call in your controller.
TryValidateModel(your model here);
After you call this in your controller call your model.IsValid property.
Make sure you register everything and you should be good to go. I assume you can fill in the missing pieces.
The big picture looks like this:

Resources