MVC 5 Remote Validation

2019-02-01 08:22发布

问题:

I need to validate an input field value from user before the form is submitted.

I have created an action in my custom controller and decorated the field with it:

action name: CheckValue controller name: Validate

[Remote("CheckValue", "Validate"), ErrorMessage="Value is not valid"]
public string Value { get; set; }

The problem is when I press submit, the form is being submitted and then the message Value is not valid is shown if the value entered by the user is not valid.

How can I validate the value entered by user and prevent the form to be submitted if value is not valid, and display the error message?

If I try in JavaScript to check if the form is valid $("#formId").valid() that returns true, that means no matter what is the status of the value (valid or not) the form is valid.

In the other hand if I decorate another field with the [Required] attribute the form is not submitted and the error is shown for that field that is required. However the validation doesn't occur behind the scene for the remote validation field.

回答1:

The complete solution of Remote Validation in MVC. It will check if the email exists in database and show the following error:

Email already exists

  1. Account Controller Action

    [AllowAnonymous]
    [HttpPost]
    public ActionResult CheckExistingEmail(string Email)
    {
        try
        {
            return Json(!IsEmailExists(Email));
        }
        catch (Exception ex)
        {
            return Json(false);
        }
    }
    
    private bool IsEmailExists(string email)
        =>  UserManager.FindByEmail(email) != null;
    
  2. Add Model Validation

    [Required]
    [MaxLength(50)]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    [System.Web.Mvc.Remote("CheckExistingEmail", "Account", HttpMethod = "POST", ErrorMessage = "Email already exists")]
    public string Email { get; set; }
    
  3. Add Scripts

    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    


回答2:

Yes, you have to add [Remote] to your model:

[Remote("ActionName", "ControllerName", ErrorMessage = "{0} Is somthing!")]
public string yourproperty { get; set; }

And Controller:

public JsonResult ActionName(string yourproperty)
{
    return Json(!db.yourproperty.Any(lo => lo.yourproperty== yourproperty), JsonRequestBehavior.AllowGet);
}

Works for me fine; I hope will useful for you.



回答3:

With the reference of c-sharpcorner demo

We can use RemoteAttribute.

Step 1

In the HomeController create a method and for that write the following.

public JsonResult IsUserExists(string UserName)   
{  
//check if any of the UserName matches the UserName specified in the Parameter using the ANY extension method.  
return Json(!db.Users.Any(x => x.UserName == UserName) ,JsonRequestBehavior.AllowGet);  
}  

You might be wondering why we are returning JsonResult back. We want the validation to occur at the client side, so we are returning a JsonResult.

Step 2

The next step is to hook this method up with the username property and for that first we need to add a class file in the models folder, add a partial User class and provide the required customization to the UserName property.

using System.ComponentModel.DataAnnotations;  
using System.Web.Mvc;   
namespace UniqueField.Models 
{  
   [MetadataType(typeof(UserMetaData))]  
   public partial class User 
   {  
   }  
class UserMetaData 
{  
   [Remote("IsUserExists","Home",ErrorMessage="User Name already in use")]  
   public string UserName { get; set; }  
}  
}  

Step 3

In create.cshtml we need to specify the source of the three jQuery files in the given order.

<h2>Create</h2>  
<script src="~/Scripts/jquery-1.10.2.js"></script>  
<script src="~/Scripts/jquery.validate.js"></script>  
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>


回答4:

You dont put the Controller code. But must to be something like this:

Your code:

[Remote("CheckValue", "Validate", ErrorMessage="Value is not valid")]
public string Value { get; set; }

My code for the controller(Validate):

public ActionResult CheckValue(string Value)
        {
            if (Value == "x value")
            {
        // This show the error message of validation and stop the submit of the form
                return Json(true, JsonRequestBehavior.AllowGet);
            }
            else
            {
        // This will ignore the validation and the submit of the form is gone to take place.
               return Json(false, JsonRequestBehavior.AllowGet);
            }
        }


回答5:

The existing answers are great but there are a couple of gotchas:

1) The validation method's parameter name has to exactly match the name of the property being validated, e.g. for

[System.Web.Mvc.Remote("CheckExistingDocumentTypeCode", "DocumentTypes", HttpMethod = "POST", ErrorMessage = "Code already exists")]
public string DocumentTypeCode { get; set; }

The validation method's parameter must be called DocumentTypeCode, including the capital letter, or else you'll get a null as the parameter instead of the value of the property being validated:

[AllowAnonymous]
[HttpPost]
public async Task<ActionResult> CheckExistingDocumentTypeCode(string DocumentTypeCode)

Be particularly wary of this if you are a Resharper user, of if you're writing multipurpose validation methods for use by more than one property.

2) I had to get this working with a Telerik grid and I had to implement it slightly differently in order to get the validation failure messages to show correctly in the grid (the examples here showed 'false' as the validation error message):

[AllowAnonymous]
[HttpPost]
public async Task<ActionResult> CheckExistingDocumentTypeCode(string DocumentTypeCode)
{
    try
    {
        if (!await IsDocTypeCodeExists(DocumentTypeCode))
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
        return Json("This Document Type Code is already in use", JsonRequestBehavior.AllowGet);
    }
    catch (Exception ex)
    {
        return Json(ex.ToString(), JsonRequestBehavior.AllowGet);
    }
}