【问题标题】:Remote validation not working in ASP.NET MVC 5远程验证在 ASP.NET MVC 5 中不起作用
【发布时间】:2019-07-17 20:51:35
【问题描述】:

在这里,我创建了包含客户电子邮件字段的表单,我正在尝试检查输入的电子邮件是否已经退出,如果存在则显示电子邮件已存在消息。

为此,我尝试使用远程验证,但问题是即使存在电子邮件,它也没有显示任何错误,它甚至没有在用于远程验证的 IsEmailExists 方法中击中控制器

对我的代码有任何帮助都会有很大帮助。谢谢

以下是我在控制器中的操作

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



以下是我的元数据

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



下面是我的部分课程

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



以下是我的视图,包括客户电子邮件

<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>
}

【问题讨论】:

  • 只是一个评论:属性'[Remote]` 在服务器端验证。
  • @redcaper71 尝试将Remote 属性直接添加到Customer 类中的CustomerEmail,而不是使用元数据?
  • @TanvirArjel 将在重新创建该类时消失,因此对元数据进行验证
  • @redcaper71 请更改方法签名如下并告诉我:public JsonResult IsEmailExists([Bind(Prefix="Customer.CustomerEmail")] string CustomerEmail)
  • @redcaper71 有更新吗?它对你有用吗?

标签: c# entity-framework asp.net-mvc-5 remote-validation


【解决方案1】:

如下更改您的方法签名以包含Bind Prefix 属性/属性。

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

现在应该可以了!

【讨论】:

    【解决方案2】:

    不确定您的源代码有什么真正的问题,但我尝试在我身边重现,它运行良好。

    这是我的源代码。

    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 文件:

    @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>
    }
    

    它跳转到方法 IsEmailExists(),这是结果输出

    可能是你错过了设置

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

    在 web.config 中?

    【讨论】:

      【解决方案3】:

      如果它没有击中控制器,则表明它不是实际验证逻辑的问题,而是您如何处理服务器的问题。

      有几点需要检查:

      您的远程验证码是否可供客户端使用?

      首先要考虑的是这是否是一个安全/身份验证问题。您可以做一些简单的事情来检查:

      • 如果您在控制器或方法上设置了身份验证属性,请尝试将其注释掉
      • 尝试注释掉任何其他身份验证代码

      如果这不能解决问题,那么当您在调试中运行应用时,尝试使用 Postman 调用您的远程验证端点并查看是否:

      • 邮递员从你的方法中得到了 200 的回报。
      • 如果是这样,请在您的代码中放置一个断点并检查它是否真正被执行。

      如果 Postman 可以到达您的端点,那么...

      你的代码有问题吗?

      我看不出您的代码中有任何明显错误,但这与我编写验证代码的方式不同。这是一个直接从我的代码中进行远程验证的示例

      这是带有远程验证集的模型属性:

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

      这是 Documents 控制器中对应的方法:

      [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);
          }
      }
      

      您可以看到我已经明确命名了模型属性上的所有参数,只是为了清楚到底发生了什么。

      比较我的代码和你的主要区别是:

      • 地雷异步。这应该没什么区别。
      • 我的控制器方法是 POST(HttpPost 属性也是如此,这也意味着我需要告诉模型 HttpMethod 也是 POST)
      • 我的远程验证方法需要两个参数,所以我通过 AdditionalFields 参数传入了一个额外的属性

      我看不出你的代码有什么问题,但是尝试一次更改它以使其更像我的工作(特别是尝试将其设置为 post 方法并命名参数)并查看是否会暴露任何问题问题。

      希望以上内容能让你更接近。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        【解决方案5】:

        您可以尝试将此代码添加到视图底部:

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

        这是我遇到的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-25
          相关资源
          最近更新 更多