Remote validation in MVC when javascript is disabled

Remote validation in MVC when javascript is disabled

Please read our last article before proceeding to this article. In our last article, we discuss Remote validation in ASP.NET MVC application. In this article, we will discuss Remote validation in MVC when javascript is disabled.

Remote attribute only works when JavaScript is enabled. If the end user disables JavaScript on his/her machine then the validation does not work. This is because RemoteAttribute requires JavaScript to make an asynchronous AJAX call to the server side validation method. As a result, the user will be able to submit the form, bypassing the validation in place. This is why it is always important to have server-side validation.

To make server-side validation work, when JavaScript is disabled, there are 2 ways

  1. Add model validation error dynamically in the controller action method
  2. Create a custom remote attribute and override IsValid() method
Add model validation error dynamically in the controller action method

We will continue with the example that we worked with in our last article. Modify the Create action method that is decorated with [HttpPost] attribute as shown below.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "UserID,FullName,UserName,Password")] User user)
{
    // Check if the UserName already exists, and if it does, add Model validation error
    if (db.Users.Any(x => x.UserName == user.UserName))
    {
        ModelState.AddModelError("UserName", "UserName already in use");
    }
    if (ModelState.IsValid)
    {
        db.Users.Add(user);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(user);
}

At this point, disable JavaScript in the browser, and test your application. Notice that, we don’t get client-side validation, but when we submit the form server-side validation still prevents the user from submitting the form, if there are validation errors.

However, delegating the responsibility of performing validation, to a controller action method violates the separation of concerns within MVC. Ideally, all validation logic should be in the Model. Using validation attributes in MVC models should be the preferred method for validation.

Creating a custom remote attribute

Step 1: Right-click on the project name in solution explorer and a folder with name = “Common”
Step 2: Right-click on the “Common” folder, you have just added and add a class file with name = RemoteClientServer.cs

Step 3: Copy and paste the following code.

namespace RemoteValidationInMVC.Common
{
    public class RemoteClientServerAttribute : RemoteAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            // Get the controller using reflection
            Type controller = Assembly.GetExecutingAssembly().GetTypes()
                .FirstOrDefault(type => type.Name.ToLower() == string.Format("{0}Controller",
                    this.RouteData["controller"].ToString()).ToLower());
            if (controller != null)
            {
                // Get the action method that has validation logic
                MethodInfo action = controller.GetMethods()
                    .FirstOrDefault(method => method.Name.ToLower() ==
                        this.RouteData["action"].ToString().ToLower());
                if (action != null)
                {
                    // Create an instance of the controller class
                    object instance = Activator.CreateInstance(controller);
                    // Invoke the action method that has validation logic
                    object response = action.Invoke(instance, new object[] { value });
                    if (response is JsonResult)
                    {
                        object jsonData = ((JsonResult)response).Data;
                        if (jsonData is bool)
                        {
                            return (bool)jsonData ? ValidationResult.Success :
                                new ValidationResult(this.ErrorMessage);
                        }
                    }
                }
            }

            return ValidationResult.Success;
            // If you want the validation to fail, create an instance of ValidationResult
            // return new ValidationResult(base.ErrorMessageString);
        }

        public RemoteClientServerAttribute(string routeName)
            : base(routeName)
        {
        }
        public RemoteClientServerAttribute(string action, string controller)
            : base(action, controller)
        {
        }
        public RemoteClientServerAttribute(string action, string controller,
            string areaName) : base(action, controller, areaName)
        {
        }
    }
}

Step 4: Open “User.cs” file, that is present in “Models” folder. Decorate “UserName” property with RemoteClientServerAttribute. 

using System.ComponentModel.DataAnnotations;
using RemoteValidationInMVC.Common;

namespace RemoteValidationInMVC.Models
{
    [MetadataType(typeof(UserMetadata))]
    public partial class User
    {
    }

    public class UserMetadata
    {
        [RemoteClientServer("IsUserNameAvailable", "Home",
            ErrorMessage = "UserName already in use")]
        public string UserName { get; set; }
    }
}

Disable JavaScript in the browser, and test your application. Notice that, we don’t get client-side validation, but when you submit the form server-side validation still prevents the user from submitting the form, if there are validation errors. 

In the next article, I will discuss Partial View in ASP.NET MVC

SUMMARY

In this article, I try to explain Remote validation in MVC when javascript is disabled in ASP.NET MVC application step by step with a real-time example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *