ASP.NET MVC Remote Validation For Multiple Fields With AdditionalFields Property

This post shows the implementation of ASP.NET MVC Remote Validation for multiple fields with AdditionalFields property and we will validate the uniqueness of a product name under a chosen category.
2011-10-24 09:44
Tugberk Ugurlu


why-wont-you-validate-me-hrrrr

I blogged about ASP.NET MVC Remote Validation couple of days ago by showing a simple scenario for how to use it. That blog post simply covers everything about remote validation except for properties of RemoteAttribute Class.

In that blog post, we covered validating user inputs uniqueness for one field in order to alert the user before the form is posted. This is a quite nice built-in feature which takes basically not more 5 minutes to implement.

But we as in all human beings tend not to be happy with the current situation and want more. It is in our nature, we can’t help that. So, as soon as I use this feature I ask myself "What if I would like to check the uniqueness of product name inside the chosen category?". Well, it turns out that ASP.NET MVC team asked this question themselves way earlier than me and added a support for this kind of situations.

RemoteAttribute.AdditionalFields Property gets or sets the additional fields that are required for validation. AdditionalFields property is string property and can be provided for multiple fields.

Probably another question pops up on your mind : "How does ASP.NET MVC Framework relate the fields, which we will provide for AdditionalFields property, with form elements and pass them our controller?" If we need to ask this question in plain English, that would be this : "How the heck does it know in which category I trying to check the uniqueness of the product name?". Here, ASP.NET MVC Model Binding feature plays a huge role here as much as JQuery.

Simple Scenario

Assume that we need to store products under a category inside our database and we need every each product name to be unique under the chosen category.

In order to stick with the topic here, I have already built the necessary stuff (database, repos, etc.). I used SQL Server Compact Version 4 here. As sample database, you won’t believe what I used : Northwind Winking smile I also used Entity Framework to reach out to the data. You can see all of the code from my GitHub Repo : https://github.com/tugberkugurlu/MvcRemoteValidationSample

Our create form looks like below :

image

The product model class looks like this :

public partial class Product
{
    public Product()
    {
        this.Order_Details = new HashSet<Order_Detail>();
    }

    public int Product_ID { get; set; }
    public Nullable<int> Supplier_ID { get; set; }
    public Nullable<int> Category_ID { get; set; }
    public string Product_Name { get; set; }
    public string English_Name { get; set; }
    public string Quantity_Per_Unit { get; set; }
    public Nullable<decimal> Unit_Price { get; set; }
    public Nullable<short> Units_In_Stock { get; set; }
    public Nullable<short> Units_On_Order { get; set; }
    public Nullable<short> Reorder_Level { get; set; }
    public bool Discontinued { get; set; }

    public virtual Category Category { get; set; }
    public virtual ICollection<Order_Detail> Order_Details { get; set; }
    public virtual Supplier Supplier { get; set; }
}

Here is my additional partial class under the same namespace of my Product class :

[MetadataType(typeof(Product.MetaData))]
public partial class Product {

    private class MetaData {

        [Remote(
            "doesProductNameExistUnderCategory", 
            "Northwind", 
            AdditionalFields = "Category_ID",
            ErrorMessage = "Product name already exists under the chosen category. Please enter a different product name.",
            HttpMethod = "POST"
        )]
        [Required]
        public string Product_Name { get; set; }
        
        [Required]
        public int? Supplier_ID { get; set; }

        [Required]
        public int? Category_ID { get; set; }

    }

}

As you see there, we have decorated Product_Name property with RemoteAttribute. What we need to point out here is AdditionalFields property of RemoteAttribute. Simply we are saying here that : 'Pass Category_ID value to the controller action when you try validate the Product_Name'. So, Ajax Request will send two form inputs to our action : Product_Name and Category_ID. As we have already seen on my previous blog post on ASP.NET MVC Remote Validation, Model Binder will bind those inputs to our action parameters in order to allow us to easily pick them.

Our main goal here is to check the uniqueness of the product name under the chosen category and that’s why we need Category_ID value inside our controller action. Check controller action code below and you will get what I am trying to say :

public JsonResult doesProductNameExistUnderCategory(int? Category_ID, string Product_Name) {

    var model = _entities.Products.Where(x => (Category_ID.HasValue) ? 
            (x.Category_ID == Category_ID && x.Product_Name == Product_Name) : 
            (x.Product_Name == Product_Name)
        );

    return Json(model.Count() == 0);

}

Inside this action, we are checking if the user name already exists under the chosen category or not. For the real purpose of this blog post, we only need to focus what we are returning here. The other part of this code mostly depends on your application’s business logic.

We are basically done here. I will run the app and see it in action but please firstly see the below screenshot :

image

This table show the list of products inside our database. On the first row, we see that there is a product named Chai under Category_ID 1 whose Category_Name is Beverages (you don’t see the Category_Name here but don’t worry, just trust me). We will demonstrate our sample with this product values.

First, select the category from the select list :

image

Then, type Chai for Product_Name :

image

Then, simply hit Tab key :

image

All done but I would like to go a little deeper here. Let’s put a break point on doesProductNameExistUnderCategory method and start a debug session.

image

When we follow the above steps again, we should end up like this :

image

Let’s look what we got here :

image

We have all the necessary values to check if the value is legitimate or not.

Again, you can see all of the code from my GitHub Repo : https://github.com/tugberkugurlu/MvcRemoteValidationSample

Hope you enjoy the post Smile



Comments

Thanigainathan
by Thanigainathan on Monday, Oct 31 2011 13:12:09 +02:00

Hi,

Post is very nice

Please let us know how to customize the script generated at the cleint side.

 

Thanks,

Thanigainathan.S

Tugberk
by Tugberk on Monday, Oct 31 2011 13:52:41 +02:00

@Thanigainathan

You need to dig into jquery.validate.unobtrusive.min.js in order to customize it.

Rune Hansen
by Rune Hansen on Wednesday, Jan 11 2012 19:51:05 +02:00

Nice post. I will try to implement this, looking over your shoulder. I think it will be easy:-)

a
by a on Monday, Sep 17 2012 07:03:04 +03:00

how to clear remote validation once it is get fired

New Comment