简体   繁体   中英

Remote validation not working in ASP.NET MVC 5

Here I have create form which consists customer email field for which I am trying to check whether the entered email already exits or not and if exist show email already exists message.

To do this i have tried to use remote validation but the problem is that its not showing any error even though email exists, it not even hitting the controller in IsEmailExists method which is used for remote validation

Any help with my code will be a great help. Thank you

Below is my action in controller

    public JsonResult IsEmailExists(string CustomerEmail)
    {
        emedicineEntities _db = new emedicineEntities();
        return Json(!_db.Customers.Any(x => x.CustomerEmail == CustomerEmail), JsonRequestBehavior.AllowGet);
    }



Below is my metadata

namespace eMedicine.Model
{
    public class CustomerMetaDta
    {
        [Remote("IsEmailExists", "Customers", ErrorMessage = "EmailId already exists.")]
        [Required(ErrorMessage = "Please Enter Emailw")]
        public string CustomerEmail { get; set; }
    }
}



Below is my partial class

namespace eMedicine.Model
{
    [MetadataType(typeof(CustomerMetaDta))]
    public partial class Customer
    {
    }
}



Below is my view consisting customer email

<link href="~/Content/Site.css" rel="stylesheet" />
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

@using (Html.BeginForm("Create", "Customers", FormMethod.Post, new { @id = "register" }))
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CustomerName, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.CustomerEmail, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CustomerEmail, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CustomerEmail, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.PasswordHash, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.PasswordHash, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.PasswordHash, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

Change your method signature as follows to include the Bind Prefix attribute/property.

public JsonResult IsEmailExists([Bind(Prefix="Customer.CustomerEmail")] string CustomerEmail)
{
    emedicineEntities _db = new emedicineEntities();
    return Json(!_db.Customers.Any(x => x.CustomerEmail == CustomerEmail), JsonRequestBehavior.AllowGet);
}

Now it should work!

Not sure what real problem with your source code, but i tried to reproduce in my side, it worked well.

Here are my source code.

namespace WebApplication1.Controllers
{
    public class CustomerMetaDta
    {
        [Remote("IsEmailExists", "Customer", ErrorMessage = "EmailId already exists.")]
        [Required(ErrorMessage = "Please Enter Emailw")]
        public string CustomerEmail { get; set; }
    }

    [MetadataType(typeof(CustomerMetaDta))]
    public partial class Customer
    {

    }

    public partial class Customer
    {
        public string CustomerEmail { get; set; }
        public string CustomerName { get; set; }
        public string PasswordHash { get; set; }
    }
    public class CustomerController : Controller
    {
        public JsonResult IsEmailExists(string CustomerEmail)
        {
            //emedicineEntities _db = new emedicineEntities();
            List<Customer> _db = new List<Customer>
            {
                new Customer { CustomerEmail  = "hien@gmail.com"},
                new Customer { CustomerEmail  = "hien1@gmail.com"}
            };
            return Json(!_db.Any(x => x.CustomerEmail == CustomerEmail), JsonRequestBehavior.AllowGet);
        }
        // GET: Customer
        public ActionResult Index()
        {
            return View();
        }
    }
}

Index.cshtml file:

@model WebApplication1.Controllers.Customer

@{
    ViewBag.Title = "Index";
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

@using (Html.BeginForm("Create", "Customer", FormMethod.Post, new { @id = "register" }))
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CustomerName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.CustomerEmail, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CustomerEmail, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CustomerEmail, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.PasswordHash, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.PasswordHash, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.PasswordHash, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

It jumps to method IsEmailExists() and this is result output在此处输入图片说明

May be you missed setting

<add key="ClientValidationEnabled" value="true"/>
 <add key="UnobtrusiveJavaScriptEnabled" value="true"/>

in web.config?

If it's not hitting the controller that suggests it isn't a problem with the actual validation logic, but more an issue with how you're addressing the server.

There are a few things to check:

Is your remote validation code available to the client at all?

The first thing to consider is could this be a security/authentication issue. There are a few simple things you can do to check that:

  • If you have authentication attributes set on your controllers or methods, try commenting them out
  • try commenting out any other authentication code

If that doesn't fix it, then when you've got the app running in debug, try using Postman to call your remote validation endpoint and see whether:

  • Postman gets a 200 back from your method.
  • If so, put a breakpoint in your code and check it is actually getting executed.

If Postman can get to your endpoint then...

Is there an issue in your code?

I can't see anything obviously wrong in your code, but it is different to how I write validation code. This is an example of some working remote validation straight out of my code

This is the model property with the remote validation set:

    [System.Web.Mvc.Remote(
        action: "CheckExistingDocumentCode",
        controller: "Documents",
        AdditionalFields = "DocumentId",
        HttpMethod = "POST",
        ErrorMessage = "Code already exists")]
    public string DocumentCode { get; set; }

This is the corresponding method in the Documents controller:

[HttpPost]
public async Task<ActionResult> CheckExistingDocumentCode(string DocumentCode, int DocumentId)
{
    try
    {
        if (!await _documentValidationRules.IsExistingDocumentCodeAsync(DocumentCode, DocumentId))
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
        return Json("This Document Code is already in use", JsonRequestBehavior.AllowGet);
    }
    catch (Exception ex)
    {
        return Json(ex.ToString(), JsonRequestBehavior.AllowGet);
    }
}

You can see that I've explicitly named all the parameters on the model property just to be clear exactly what's going on.

Comparing my code to yours the main differences are:

  • Mines async. That shouldn't make any difference.
  • My contrller method is a POST (so is has the HttpPost attribute, which also means I needed to tell the model the HttpMethod was POST too)
  • My remote validation method takes two parameters, so I'm passing in an extra property via the AdditionalFields argument

I can't see what the issue is in your code, but try changing it a piece at a time to work more like mine (particularly, try making it a post method and naming the parameters) and see if that exposes any issues.

Hopefully something in the above will get you closer.

没有人提到会导致您的症状的一件事:如果该方法需要由匿名用户执行并且您的方法上没有 AllowAnonymous 属性,则该方法将不会触发(并且提交按钮不会执行任何操作。

I'm experiencing the same issue with remote validation. The only way I can get it to work in my project is by downgrading jquery from 3.4.1 to 1.10.2. Once I downgrade it works fine??

I am new to web programming so not sure if downgrading to such an old version is prudent.

Does remote validation work in newer releases of Jquery?

You can try to add this code to the bottom of your View:

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

This is the issue I had.

I was stuck with a similar problem. I had tried every possible means of remote validation mentioned in the documentation by Microsoft and other resources on the internet. Double-triple checked everything, Still no luck. Finally, this resource that uses ModelState.AddModelError is what worked for me. It's not the best or the most efficient way, but it worked for me.

Action

  [AllowAnonymous]
        public async Task<IActionResult> IsEmailInUse([Bind("Email")]Register model)
        {
            var user = await _userManager.FindByEmailAsync(model.Email);
            if(user == null)
            {
                return Json(true);
            }
            else
            {
                return Json($"Email {model.Email} is already Taken by another user");
            }
        }

RegisterVM

 public class Register {
        [Required]
        [EmailAddress]
        [Remote(action:"IsEmailInUse",controller: "Account")]
        public string Email { get; set; }
        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
        [Required]
        [DataType(DataType.Password)]
        [Display(Name ="Confirm Password")]
        [Compare("Password",ErrorMessage ="Not Equal")]
        public string ConfirmPassword { get; set; }
    }

Scripts

<script src="/lib/jquery/jquery.js"></script>
 <script src="/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM