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

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.

Related

Understanding relations between model view and controller

I went through a lot of readings about MVC and what each of these does is more or less clear. What I haven't understood yet is how they relate. I mean, I know about these relationships
but how are they implemented? What happens in an MVC framework?
I also have a few questions:
I read that a view can't be coupled with the controller, in other words it can't have a controller object inside, but then how does it use the proper controller if a view is supposed to trigger something in it?
How can the model update the view if its unique job is to represent data?
Is the business logic inside the controller or the model? I have read conflicting points of view
The most basic explination of MVC would be that you have each of the 3 layers.
Model
This contains your data. i.e database or set of classes.
View
This displays data to the user i.e your HTML page.
Contains controls for user interaction.
Controller
All access to data should go through this layer. i.e load data from your data source(model) and save data to your data source.
Carries out any data manipulation before saving or loading.
This create a separation of concerns theoretically allowing you to change anything in either layer without the other layer knowing or caring making for far more maintainable and readable code.
In practice this can become more complicated depending on how you wish to access data and display it although the basic principles still apply, occasionally meaning that each part of MVC pattern could be made up of smaller parts.
In terms of implementing it a good example would be ASP.Net MVC http://www.asp.net/mvc. the following could be a simple implementation of displaying some data via MVC using C#.
Model (C# class)
public class Person{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Controller
public ActionResult Index(){
return View(new Person() { FirstName = "Person", LastName = "1" });
}
View (Index.cshtml)
#model Person
Full name: #Html.Raw(Model.FirstName + " " + Model.LastName)
This would output onto the web page
Full name : Person 1
Please forgive me for any syntax errors, not tested.
More detailed post: http://www.tutorialspoint.com/design_pattern/mvc_pattern.htm

ASP.NET MVC Fluent Validation doesn't work on the client side for view model's property which is another type of class

I've an ASP.NET MVC application using Fluent Validation. Basically there is a view model Book which has an author as a property on it, like:
class Book {
string Title { get; set; }
Author Author { get; set; }
...
}
class Author {
string Name { get; set; }
...
}
On the view there is a field for the Book.Author.Name.
#Html.EditorFor(m => m.Author.Name)
There is Fluent Validation rule set up for the Book view model something like this
RuleFor(book => book.Author.Name).NotEmpty();
Then I find that this validation won't be fired for the Book.Author.Name field on client side. When inspecting the field's HTML markup, I found that no validation data attributes have been generated. Seems like Fluent Validation cannot handle the multiple level structure properly to generate the client side validation markups. But after it is posted back to the server, the server side validation fires as expected for this field. How can I get the validation fired on the client side?
Eventually to work around this problem, I had to create a custom editor template for the Author class, and a separate Fluent Validator for the Author class with all the rules I needed for the properties on the Author class. This approach worked perfect in this case. The client side validation could be fired as expected this time, and so does the server side as well.
By the way, I've also tried to create a partial view instead of a custom editor template for the Author class. The client side validation was able to be fired, but after post back the partial view couldn't be bound to the Book.Author for the controller's action method.

Model Validation in asp .net MVC

I am developing an application where I have a form with a model "StudentListModel".
I have a button in the same page which is not a submit button. I have written an ajax function which calls an action method in the controller specified.
Now my problem is there is a textbox for the studentname ,
[StringLength(160, MinimumLength = 3)]
[Display(Name = "First Name")]
[Required]
[Remote("CheckDuplicateNames", "AddStudent")]
public string StudentName { get; set; }
None of these validations are firing.However if I make the button as submit ,these will work.
Is there any way to do model validation other than using formsubmission?
Model validation is done automatically before your ActionMethod is executed and ModelState will be populated with information about that validation. You do not need to call ValidateModel as long as you are running your Controller and ActionMethods in the default MVC lifecycle.
An action method that has parameters will have the values for parameters populated using MVC Model Binding. This means that any values posted in a Form or QueryString (and a few other sources) will be name matched to simple parameters or properties in complex parameters. Using an HTML form and the MVC HtmlHelper methods for creating input types you get the desired behavior with very little work, but as you have noted it requires a form submit to send the data.
An ajax call will also populate the model using Model Binding but it requires the fields to be sent to the ActionMethod. Using jQuery it is as simple as performing a post or get request on the buttons click event passing a JavaScript object with your model's properties on it.
$('#yourButtonId').click(function() {
var student = {};
student.StudentName = $('#StudentName').val();
$.post('#Url.Action("ActionMethodName")', student).done(function (data) {
//handle returned result from ActionMethod}
});
});
You can call model validation manually in the controller method. The syntax is simply ValidateModel(model). This validates the model based on its current property values, and populates the ModelState dictionary with any errors.
If your model does not get populated with the values, but you have got them at hand, you can populate it using UpdateModel(model, values), another method inherited from the Controller class.

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.

MVC3 validate only one entity in ViewModel

I have an mvc3 create page using a View Model with 2 entities
like
class ViewModel1{
public User user{get;set;}
public Company company{get;set;}
}
where User and Company are EF4 entities(tables). I need to use a single page to create both(related) tables. Now the Company entity is optional under some conditions and I use jQuery to hide the corresponding section in the view.
However since company has required fields , the post back create function has ModelState.Valid as false.
What I want to do is if the Company section is hidden, I would like to skip validating the Company entity in ViewModel in Server( I avoid validation of hidden elements in Client).
Maybe there is a better and more proper approach to this?
What you have shown is not a view model. You call it a view model but it isn't because it is referencing your EF domain entities.
A more realistic view model would look like this:
class ViewModel1
{
public UserViewModel User { get;set; }
public CompanyViewModel Company { get; set; }
}
or even flattened out and containing only the properties that your view needs:
class ViewModel1
{
public int UserId { get;set; }
[Required]
public string FullUserName { get;set; }
[Required]
public string CompanyName { get; set; }
}
Now depending on your specific requirements about view model validation your UserViewModel and CompanyViewModel classes will be specifically designed for them.
Instead of putting the entities directly in the view model, put the properties for the entities in the view model and map between the view model and the actual entity objects on the server. That way you can control what properties are required for your view. Create some custom validation rules to validate that the required company properties are there when some company information is required. To do this on the server, you can have your view model implement IValidatableObject and implement the logic in the Validate method. On the client you can add rules to the jQuery validate plugin for the "required if" properties.
public class UserCreationViewModel : IValidatableObject
{
[Required]
public string Username { get; set; }
[Required]
public string FirstName { get; set; }
...
public string CompanyName { get; set; }
public string CompanyEmail { get; set; }
public IEnumerable<ValidationResult> Validate( ValidationContext context )
{
if (!string.IsNullOrEmpty(CompanyName) && string.IsNullOrEmpty(CompanyEmail))
{
return yield new ValidationResult("Company Email is required if you specify a company", new [] { "CompanyEmail" });
}
}
}
I'm not sure what I would do on the client-side. You have a choice of either adding specific rules to the validate plugin directly, but it might be hard to make it look exactly the same as using the unobtrusive validation that MVC adds. Alternatively, you could look at adding/removing the unobtrusive attributes from the "required if" elements using jQuery depending on the state of the elements that trigger their requirement. I suggest trying both ways -- look at the docs for the validate plugin to see how to add custom rules and examine the code emitted by the MVC framework for the unobtrusive validate to see what you would need to add to make that work.
Another possibility would be including/removing a partial view with the company properties in the from based on whether the company information is required or not. That is, type in a company name and use AJAX to grab the inputs required for the company and add them to the form. If the company name is deleted, delete the elements. Leave the server-side validation the way it is, but in the partial view mimic the HTML that the framework would add in for unobtrusive validation. This is sort of the best of both worlds as the jQuery code is much simpler and you get consistent validation, too.
There are many ways you can achieve,
1) more commonly donot use [Required] attribute on Company object, but have proper validation for parameters inside Company object.
In this case if Company object is null still validation will pass, but if Company object isnot null it will validate each properties.
2) If validation involves some complex business logic, then go for Self Validating Model. (inherit from IValiddatableObject, and override Validate(...).
3) By code, in the controller.
if(model.company == null)
this.ModelState.Keys.Where(k => k.Contains("company")).ToList().ForEach(k => this.ModelState.Remove(k));
first two are best approved approaches, third is just another way to achieve your functionalities

Resources