localizing mvc 3.0 validation client messages - asp.net-mvc-3

At first sorry for Microsoft MVC team because of no simple solution for localizing data annotation validation messages. It takes me a lot of time and finally no simple solution found!
I finally decided to inherit from RequiredAttribute to do localization. so I did this :
public class MyRequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute
{
public MyRequiredAttribute()
: base()
{
this.ErrorMessageResourceType = typeof(Resources.DataAnnotationDefaults);
this.ErrorMessageResourceName = "Required";
}
}
where I provided my localized messages in DataAnnotationDefaults.resx file.
So I can use this simply
[MyRequired]
public int UnitCode { get; set; }
But the problem is: it doesn't apply in client-side and just in server-side. why? what did I miss?
It is amazing that the following line is ok and works in client-side too!
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(DataAnnotationDefaults))]
public int UnitCode { get; set; }
I will be glad and appreciated if someone can help me on this.

You need to understand how validation works in MVC and .NET. DataAnnotation is a generic validation library which can be used in all kinds of applications and not just MVC.
Hence MVC contains different types of adapters for MVC which is used to add support for DataAnnotations. The client-side adapters are specifically made for the attributes defined in System.ComponentModel.DataAnnotations.
You therefore need to create your own adapters to get it working with your derived attributes. I've written a blog entry about it.
The easier approach is to use my localized metadata provider.

Related

Server-side validation

I am having trouble figuring out how to get server-side DbContext validation errors back to the client. I understand that Breeze has default validators that react to a few of the attributes such as Required, but what about all the other attributes? I could write a custom JavaScript validator for Breeze that will check on the client side, but I also need to check to make sure the entity is valid on the server-side.
For example, the application requires a Person to to have a valid email address. A malicious user comes along and gets an email address past the client and posts to the server with a data that would not pass the EmailAddress validator. Thus far my experience with Breeze is that the email address will save and not bubble up any DbContext Entity Framework errors.
Assuming the model below, what would be the best way to get any entity validation errors?
public class PeopleContext : DbContext
{
public PeopleContext()
: base("name=ConnectionString"){ }
public DbSet<Person> People { get; set; }
}
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[EmailAddress]
[Required]
public string Email { get; set; }
}
UPDATE 1:
Here are some instructions to re-create the issue that I am experiencing.
Follow the instructions to create the "Todo" sample (http://www.breezejs.com/documentation/start-nuget)
Add a new custom validator to the BreezeSampleTodoItem.cs file:
[AttributeUsage(AttributeTargets.Property)]
public class CustomValidator : ValidationAttribute
{
public override Boolean IsValid(Object value)
{
string val = (string)value;
if (!string.IsNullOrEmpty(val) && val == "Error")
{
ErrorMessage = "{0} equal the word 'Error'";
return false;
}
return true;
}
}
Decorate the Description field with the new custom validator:
[CustomValidator]
public string Description { get; set; }
Add the proper usings of course (System and System.ComponentModel.DataAnnotations).
Run the project.
In one of the description fields type "Error" and save.
This is where I would expect to see an error come up through Breeze, or even an DbEntityValidationException be thrown from Entity Framework. I have tried on 2 separate computers with the same result. The entity saves to the database as if there were no error. In fact, if you put a breakpoint anywhere inside IsValid method of the custom validator you will see that its not even being called.
As of Breeze v 0.78.1 all registered DbContext server side validations will now execute during an EntityManager SaveChanges call. Any exceptions encountered will cause the save to rollback, and any validation errors to be serialized back to the Breeze client.
Note that this functionality is not yet supported for older ObjectContext ( as opposed to DbContext) based EF models.
And ... thanks to adamlj for discovering this issue and suggesting the solution.
I'm not sure what you mean by
get server-side DbContext validation errors back to the client
You could mean that you want the validation error messages to be sent to the client. But the rest of your question suggests that you want to know (a) how to run a custom validation on the server and (b) how to acquire and run a corresponding JavaScript version of that validation on the client. I will address this interpretation of your question.
Server
The Entity Framework (which you're using in your example) automatically runs Data Annotation validation rules for you ... unless you've disabled that feature manually. If you create custom validation rules in the proper way, EF will run these as well. This post by Daniel Wertheim describes how to write such rules. I can't vouch for that post in every detail but it seems correct to me. It even defines a custom Email-validationattribute!
If authoring a custom Data Annotation validation rule seems too Baroque to you (as it often does to me), you can write and call your own validation logic in one of the BeforeSave... methods discussed in "Server-side Interception".
I think these are your best server options. On to the client ...
Client
Breeze registers client-side JavaScript validations to match certain of the server-side Data Annotations (e.g., Required and MaxLength) that come across the wire in the metadata. As I write, custom Data Annotations are not recognized nor included in the metadata and they have no out-of-the-box analogs on the client. If you want the client to prescreen your entities using these rules, you'll have to write your own corresponding JavaScript validators and register them for the pertinent entity types as discussed in the Validation documentation page.
If you have suggestions or better alternatives, we'd love to hear them.

Server validation does not trigger when submitting with Ajax Asp Mvc3 with kendo + knockout

I have Asp Mvc3 app. In my view I am using kendoui + knockoutjs. I am handling the client side validation with kendo validator. I am very new to asp mvc3 and I cannot make my server side validation work.
This is my business object:
[Validator(typeof(FranchiseInfoValidator))]
public class FranchiseInfo
{
public string FullName { get; set; }
public string ShortName { get; set; }
}
}
I am using FluentValidation. This is the implementation of my validation rules:
public class FranchiseInfoValidator : AbstractValidator<FranchiseInfo>
{
public FranchiseInfoValidator()
{
RuleFor(franchiseInfo => franchiseInfo.FullName).NotEmpty();
RuleFor(franchiseInfo => franchiseInfo.ShortName).NotEmpty();
}
}
This is my view model:
public class FranchiseInfoViewModel
{
public string FullName { get; set; }
public string ShortName { get; set; }
}
This is my view strongly typed to FranchiseInfoViewModel:
#model MvcApplication2.Models.FranchiseInfoViewModel
<script src="../../Scripts/Details.js" type="text/javascript"></script>
<form id="franchiseForm" action="" style="font-family: Trebuchet MS, Verdana, Helvetica, Sans-Serif;">
<table>
<tr>
<td><label for="fullName">FullName:</label></td>
<td><input id="fullName" data-bind= "value: FullName" /></td>
</tr>
<tr>
<td><label for="shortName">ShortName:</label></td>
<td><input id="shortName" data-bind= "value: shortName" /></td>
</tr>
</table>
<button id="submit" class="k-button" data-bind="click: save" form="franchiseForm">Save Franchise</button>
</form>
On submit the form I am calling javascript function save:
$(function () {
save = function () {
// some logic
$.ajax({
url: "/franchise/SaveFranchise",
type: "POST",
data: { franchiseInfoViewModel: jsonData },
dataType: 'json',
success: function (data, textStatus, xhr) {
window.location.href = data.redirectToUrl;
}
});
}
});
On save I am submitting the data in json format and sending the data to the SaveFranchise Controller:
public ActionResult SaveFranchise(string franchiseInfoViewModel)
{
var franchiseInfoVM = JsonConvert.DeserializeObject<FranchiseInfoViewModel>(franchiseInfoViewModel);
if (!ModelState.IsValid)
{
// do some action
}
return View();
}
What I want to accomplish is on (!ModelState.IsValid) to return back to the view and show fluent validation error messages. For some reason, in my case ModelState.IsValid is always true.
As mentioned, I am very new to Asp Mvc 3. From the articles I have read, the examples are submitting the form to the server (without javascript) where there is binding and the server validation messages are returned to the view. But there the view is implemented with Razor and client side validation is done via jquery.
In my view I am using javascript view model with databindings ( kendoui + knockout). What should I do to do the server side validation in my case. Please help me. Thank You for your time and effort!
Short answer:
You should make use of model bindings in the controller action - doing so enables you to make use of ModelState.IsValid.
So your controller action:
public ActionResult SaveFranchise(string franchiseInfoViewModel)
.. should be changed into something like:
public ActionResult Create(FranchiseInfo franchiseInfo)
Be sure to post your form in a format that enables the model binder to instantiate an instance of the FranchiseInfo model. You can use JSON to do so, but I think it would be better (and simpler) if you just post the form using the standard action attribute on a form.
Elaborated answer:
One of the first things I would recommend, is that you use the model validation provided by the ASP.NET MVC framework including model bindings, model state, and data annotations for server side validation, as well as unobtrusive javascript for client side validation. Doing so would give you a way more DRY implementation with clear Separation of Concerns (SoC).
To get there - I suggest you first start taking a look at model bindings in ASP.NET MVC.
As stated in "The Features and Foibles of ASP.NET MVC Model Binding":
With model binding, controller actions can be focused on providing business value and avoid wasting time with mundane request mapping and parsing.
To see this, this MSDN article have a good definition of a model binder:
A model binder in MVC provides a simple way to map posted form values to a .NET Framework type and pass the type to an action method as a parameter. (...) Model binders are like type converters, because they can convert HTTP requests into objects that are passed to an action method.
With that abstraction in hand, you will quickly see that the signature of:
public ActionResult SaveFranchise(string franchiseInfoViewModel)
.. could be changed into something like:
public ActionResult Create(FranchiseInfo franchiseInfo)
... and at this point, things are already starting to look more clean because code like your custom data mapping:
var franchiseInfoVM = JsonConvert.DeserializeObject<FranchiseInfoViewModel>(franchiseInfoViewModel);
... can be removed.
In general, you should not need to serialize the form into JSON and post that - instead you should take advantage of the model binding in MVC and submit the form data the standard way ( by using the action attribute on the form element - well, the model binder is able to bind objects based on JSON, but I think you get my point.. ). Actually, ASP.NET MVC makes it really simple to generate a form for a model using Html.BeginForm - an example use of this is shown here.
So, now when you have refactored the view to make use of a form that posts its data without serializing the form data into JSON, you should take a look at the data annotations in MVC3.
As mentioned in this example, the System.ComponentModel.DataAnnotations namespace of .NET...
provides a built-in set of validation attributes that you can apply declaratively to any class or property. (...) The validation attributes specify behavior that you want to enforce on the model properties they are applied to.
One of the available annotations is the Required attribute - it defines that a particular model property must have a value. There are several other attributes like Range, MaxLength, RegularExpression, etc. An example use of some of the attributes could look like this:
public class Movie
{
public int ID { get; set; }
[Required(ErrorMessage = "Title is required")]
public string Title { get; set; }
[Required(ErrorMessage = "Date is required")]
public DateTime ReleaseDate { get; set; }
[Required(ErrorMessage = "Genre must be specified")]
public string Genre { get; set; }
[Required(ErrorMessage = "Price Required")]
[Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
}
( The example is borrowed from: http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/adding-validation-to-the-model )
Populating your models with data annotations makes it very easy for you to check if the model is valid or not, at the point when a given form has been submitted, and your are about the check the validity of the provided model in a given action - it is here ModelState.IsValid proves to be useful.
As mentioned in this post:
(...) The second Create method calls ModelState.IsValid to check whether the movie has any validation errors. Calling this method evaluates any validation attributes that have been applied to the object.
So at this point, you should be able to see that using data annotations to declare constraints/required behavior on your model will allow you to have a simple implementation where the logic is defined in the model and can easily be checked using ModelState.IsValid.
To expand a bit on this I can tell you a bit of my experience with model validation at server and client side in ASP.NET MVC3.
As you might already have guessed, my best experience with ASP.NET MVC3 when it comes to model validation is using data annotations and the built-in support for server-side validation through ModelState.IsValid and client-side validation through unobtrusive JavaScript.
For data annotations I use a combination of the built-in annotations, and the extensions provided by the data annotation extension project.
There are a couple of good things about using ASP.NET MVC3's support for unobtrusive client validation.
First of all, SoC is really easy to achieve, as the model validation logic is only defined one place - and that is in the model where it belongs.
Secondly you can get a more DRY implementation in your view ( avoid duplicated logic and get code that is easier to maintain ) and let the framework do the heavy lifting for you instead.
An example of how to use unobtrusive client side validation in ASP.NET MVC3 can be found here.
However, there are times when using the annotations might not seem that straigt forward - for instance when you want to validate properties such as credit cards and file extensions. In these cases where the need for logic calls for alternatives other than the basic annotations, I tend to use data annotation extensions ( unless I can target my application for .NET 4.5 which, for instance, has added a series of more attributes, like e.g. the FileExtensionAttribute ) as they provide a series of great annotation extensions that just works right out of the box ( there exist a data annotation extensions nuget package for MVC3 - so it is really simple to set up and start using ).
There are also special cases when you might have a property that depends on the state of your databse - e.g. if you want to check if a username already exists when a user is filling out a user registration form. In this scenario, the ASP.NET MVC3 remote validation annotation is your friend. As this MSDN article states:
ASP.NET MVC 3 provides a mechanism that can make a remote server call in order to validate a form field without posting the entire form to the server. This is useful when you have a field that cannot be validated on the client and is therefore likely to fail validation when the form is submitted.
And the nice thing about remote validation in ASP.NET MVC3 is, that it also is expressed using a data annotation ( as illustrated in this blogpost and in this MSDN article ).
So to sum up - using these framework features (imo) really gives you a serious range of tools to cover more or less any kind of model validation "the right way" in ASP.NET MVC3.

using System;MVC Storefront- Rob Conery reference tricky?

I follow the StoreFront MVC Application video tuturial made by rob conery.
I noticed that the Commerce.MVC.Web reference both the Commerce.MVC.Data and Commerce.MVC.Services. This is because the Commerce.MVC.Web needs the Commerce.MVC.Data because of the entities defined with in it.
What is the better way to reference the Commerce.MVC.Services only. Do I need to put the Entities in the service?or any suggestions?
The bold text is came from Commerce.MVC.Data:
Commerce.MVC.Data
Commerce.MVC.Services- reference the Commerce.MVC.Data
Commerce.MVC.Web - reference both the Commerce.MVC.Data and Commerce.MVC.Services
Here the sample code from CatalogController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Commerce.MVC.Data;
using Commerce.MVC.Services;
namespace Commerce.MVC.Web.Controllers {
public class CatalogController : Controller {
#region .ctor
ICatalogService _catalogService;
public CatalogController(ICatalogService catalogService) {
_catalogService = catalogService;
}
#endregion
#region ViewData
/// <summary>
/// Class used for transferring data to the View
/// </summary>
public class CatalogData {
public CatalogData() { }
public CatalogData(List<Category> categories, Category parent, Category child) {
this.Categories = categories;
this.Category = parent;
this.SubCategory = child;
}
public IList<Category> Categories;
//The below is came from Commerce.NVC.Data
public Product Product { get; set; }
public Category Category { get; set; }
public Category SubCategory { get; set; }
}
#endregion
}
}
Edited Response...
You can use the Service just fine, but the service returns something and that something is your Entities. In order for your Web app to use those Entities it needs to reference the class containing the Entities right?
Now you can get around this by returning Anonymous types, or maybe creating your own DTOs - but then you lose validations and everything the Entity has declared on it. In effect - you're duplicating your code.
Do you see this?
I don't think it matters massively (no pun intended) but we generally separate out the entities into a Model assembly which is shared across all layers.
So our structure is:
Company.Project.Model
Company.Project.Infrastructure
Company.Project.Web
Company.Project.Services
Company.Project.Data
The Model and Infrastructure (cross cutting concerns) are referenced across all layers with Web/Services/Data only able to talk to the layer immediately below.
Hope that makes sense.
I think the architecture in Rob's app is fine.
If you are worried that code from the website will call your data access code directly, rather than via the service, this is a legitimate concern.
However, if your website is setup with a dependency injection framework, you will not see data access classes being instantiated.
This should reduce the chances of someone new to your project instantiating data access classes directly, which obviously would be very bad...
This is why projects should always have code reviews. :)
I emailed this same question to Rob about a year ago and his response made me realise I was confusing the physical separation of code with the logical separation using namespaces.
If you still dont want to reference the entities from two different namespaces then you can use view models to dis-intermediate (and use a tool like automapper) however this is much more code.

How to programatically turn on/off a Data Annotation Validation Attribute

So, I am using ASP.NET MVC 3 and Entity Framework 4.1 (code-first).
I have a class like this:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
[Range(18, 99)]
public int Age { get; set; }
}
The range validation is fired correctly. But, for example, in some situations I would like to change the range for the Age attribute. Or even turn it off. How could I do it without changing my Model class? Is this possible to made programatically?
You can use the IValidatableObject interface and define custom validation rules.
See my answer at:
Using Data Annotations to make a field required while searching for another in a form mvc 3
Its usually just a matter of implementing the interface and determine when to enforce your rules.
I just realised the solution for this case.
Eg. A user can have an authorization to create a 14 years old person.
Before save the Model, we can invoke DataContext.GetValidationErrors() and infer if the only error validation is that we want to disable, and then set
DataContext.Configuration.ValidateOnSaveEnabled = false;
So, this way we are able to save the model.
Yes, it is possible to inject validators programmatically. Altering existing validators presents separate issues, as some attributes are read-only, so you may have to delete and replace your existing validator.
You can add a class to work on the validators by following my answer to this question.

How to iterate through all MVC Action Handlers to ensure they're in a SiteMap?

I'm working on writing a non-trivial "unit test" (perhaps better called a "UI test"?). In this case, I think I want a test that (reflectively?) finds all appropriate action handlers and then verifies that our SiteMap has a node for those Action Handlers. What I need is to identify when a developer adds a page to our system and forgets to add it to the SiteMap (this seems to be a common problem and I'd like to make it go away, which a test should easily be able to do for us). Ultimately, we want to make sure that any page that a user can land on will have a home in our SiteMap so that it builds the appropriate breadcrumb to tell the user where they are in our system (that breadcrumb part already works perfect for us, as long as the page is in the SiteMap). I would much rather try to do this with a test than try to force some policy/procedure update on us that is yet another thing we have to deal with.
Any tips on some existing code to start from in this endeavor? And if not, any thoughts on the best way to do this?
One possibility that I am considering is to reflectively identify any method that is decorated with the AcceptVerbs attribute which doesn't have a return type of JsonResult (and perhaps a couple others which would clearly not be "web pages" such as FileResult). And perhaps limit my search by first identifying classes which inherit System.Web.Mvc.Controller.
I'd love to hear a better way to do this, though. And would love even more if most of this was already written and shared to save me some time. :-)
I see this is mvc application=>
your solution would lie in routing(for me_)
you know every option which is not marked as [nonaction] is registered in Global.asax
which contains
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
and in this routes you will be able to find all accessible methods =>eg actions
this is created in basic mvc
Hope this will help
Here is the important part of my solution. This works well for us.
var mvcAssembly = typeof (AccountController).Assembly;
AllControllers = mvcAssembly.GetTypes().Where(type => type.IsSubclassOf(typeof (Controller))).ToList();
UnfilteredActionHandlers = new List<MethodInfo>();
foreach (var controller in AllControllers)
{
UnfilteredActionHandlers.AddRange(controller.GetMethods()
.Where(methodInfo =>
typeof (ActionResult).IsAssignableFrom(methodInfo.ReturnType)
&& !ControllerClassesToIgnore.Contains(methodInfo.ReflectedType)));
}
We have a few collections that we filter the UnfilteredActionHandlers collection by depending on how we want to use them:
internal List<MethodInfo> UnfilteredActionHandlers { get; set; }
internal List<MethodInfo> ActionHandlersExcludingFilteredReturnTypes { get; set; }
internal List<MethodInfo> ActionHandlersFilteredByAttributes { get; set; }
internal List<MethodInfo> ActionHandlersFilteredByBoth { get; set; }
internal static List<Type> ReturnTypesToIgnore { get; set; }
internal static List<Type> RequiredAttributes { get; set; }
internal static List<Type> ControllerClassesToIgnore { get; set; }

Resources