【问题标题】:Make checkbox required with Data Annotations使用数据注释使复选框成为必需
【发布时间】:2020-11-10 17:24:35
【问题描述】:

我想向用户显示消息,如果未选中复选框,他必须在提交表单后接受条款,如果选中复选框,则提交表单。

我的模型上有这个代码:

public class UserClass
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required(ErrorMessage = "Entry ID")]
    public int ID { get; set; }
    [Required(ErrorMessage = "Entry Name")]
    public string Name { get; set; }
}

控制器:

private readonly ApplicationUserClass _auc;
public abcController(ApplicationUserClass auc)
{
    _auc = auc;
}

public IActionResult Index()
{
    return View();
}

public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(UserClass uc)
{
    _auc.Add(uc);
    _auc.SaveChanges();
    return View();
}

查看:

<div class="row">
    <div class="col-md-9">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="ID" class="control-label"></label>
                <input asp-for="ID" class="form-control" />
                <span asp-validation-for="ID" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="sumbit" class="btn btn-primary" />
                </div>
            </div>
            <b>@ViewBag.message</b>
        </form>
    </div>
</div>

我看到了很多例子,但没有用。谁能给点建议?

【问题讨论】:

    标签: c# .net asp.net-core-mvc


    【解决方案1】:

    您可以参考以下示例:

    1. 创建一个 UserViewModel 来在 View 和控制器之间传输数据:

       public class UserViewModel
       {
           [Required(ErrorMessage = "Entry ID")]
           public int ID { get; set; }
           [Required(ErrorMessage = "Entry Name")]
           public string Name { get; set; } 
           //use custom validation method
           [CheckBoxRequired(ErrorMessage ="Please checked the items")]
           public bool IsAccepted { get; set; } 
       }
      
    2. 添加自定义验证方法:

       public class CheckBoxRequired : ValidationAttribute
       {
           protected override ValidationResult IsValid(object value, ValidationContext validationContext)
           {
               //get the entered value
               var student = (UserViewModel)validationContext.ObjectInstance;
               //Check whether the IsAccepted is selected or not.
               if (student.IsAccepted == false)
               { 
                   //if not checked the checkbox, return the error message.
                   return new ValidationResult(ErrorMessage == null ? "Please checked the checkbox" : ErrorMessage); 
               }
               return  ValidationResult.Success;
           }
       }
      
    3. 创建 Action 方法来创建用户并使用 UserViewModel 在 View 和 Controller 之间传输数据。

           public IActionResult CreateUser()
           {
               return View();
           }
           [HttpPost]
           public IActionResult CreateUser(UserViewModel user)
           {
               if (ModelState.IsValid)
               {
                  //after validation success, create a UserClass instance based on the ViewModel, and insert the "newuser" into database.
                   var newuser = new UserClass();
                   newuser.ID = user.ID;
                   newuser.Name = user.Name;       
                   //save the newuser into the database via dbcontext
                   _dbcontext.UserClass.Add(newuser);
                   _dbcontext.SaveChanges();
                   return RedirectToAction(nameof(Index));
               }
               return View();
           }
      
    4. 创建一个 CreateUser 视图页面:

           @model WebApplication2.Models.UserViewModel
      
           @{
               ViewData["Title"] = "CreateUser";
               Layout = "~/Views/Shared/_Layout.cshtml";
           } 
           <div class="row">
               <div class="col-md-6">
                   <form asp-action="CreateUser">
                       <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                       <div class="form-group">
                           <label asp-for="ID" class="control-label"></label>
                           <input asp-for="ID" class="form-control" />
                           <span asp-validation-for="ID" class="text-danger"></span>
                       </div>
                       <div class="form-group">
                           <label asp-for="Name" class="control-label"></label>
                           <input asp-for="Name" class="form-control" />
                           <span asp-validation-for="Name" class="text-danger"></span>
                       </div>
                       <div class="form-group form-check">
                           <label class="form-check-label">
                               <input class="form-check-input" asp-for="IsAccepted" /> @Html.DisplayNameFor(model => model.IsAccepted)
      
                           </label>
                           <span asp-validation-for="IsAccepted" class="text-danger"></span>
                       </div> 
                       <div class="form-group">
                           <input type="submit" value="Create" class="btn btn-primary" />
                       </div>
                   </form>
               </div>
           </div> 
      
           @section Scripts {
               @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
           }
      

    然后,截图如下:

    【讨论】:

    • 您好,我发现 [CheckBox Required(Error Message ="Please check the items")] 在我错过单击复选框时无法显示此消息。你知道发生了吗?谢谢!
    【解决方案2】:

    这可以通过一个用于验证布尔值的新 Attribute 类来完成,然后将其放置在一个新的布尔属性上。

    示例属性类:

    public class MustBeTrueAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            if (value == null) return false;
            if (value is bool b) return b;
    
            throw new InvalidOperationException("Can only be used on boolean properties.");
        }
    }
    

    使用布尔属性扩展 UserClass,包括新的属性:

    public class UserClass
    {
        // existing properties here
    
        // new property -->
        [MustBeTrue(ErrorMessage = "You need to accept the terms")]
        public bool Accepted { get; set; }
    }
    

    将新元素添加到视图中:

    <div class="form-group">
        <label asp-for="Accepted" class="control-label"></label>
        <input asp-for="Accepted" class="form-control" />
        <span asp-validation-for="Accepted" class="text-danger"></span>
    </div>
    

    最后,修改你的 Controller Post 动作方法来检查模型是否有效:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create(UserClass uc)
    {
        if (!ModelState.IsValid)
            return View(uc);
    
        _auc.Add(uc);
        _auc.SaveChanges();
        return View(uc);
    }
    

    最后一点:
    我将Accepted 属性添加到类UserClass 中,您可以使用它与MVC 交互并保存到数据库中。
    但是,您可能不希望在您的数据库表中拥有这个新属性。
    如果是这种情况,那么您将需要引入一个 UserModel 类来与 MVC 交互(with Accepted 属性)并保持 UserClass 没有 Accepted 属性,然后添加代码以在加载和显示数据时从 UserClass 映射到 UserModel + 当从 MVC 接收到需要保存的数据时从 UserModel 映射到 UserClass 的代码。

    【讨论】:

    • 你好彼得,谢谢你的建议!!!!另外,我想知道 If (value is boolean b) return b; B 是什么意思??谢谢!
    • b 是在if() 检查中隐式创建的变量的名称,如下所示:如果value 的类型为bool,则b 设置为@ 987654338@。从 C# 7 开始这是可能的,更多信息请参见此处:docs.microsoft.com/en-us/dotnet/csharp/…
    • 没问题,欢迎投票或接受答案。
    • 您好先生,关于最后一点,我的数据库有两列(Id,name)。如果我不想为“接受”插入新列。我需要为句柄“接受”创建新模型?谢谢
    • 是的,正如我试图解释的那样,您将需要两个类:一个用于保存到数据库/从数据库中读取(UserClass,或者更好地将其命名为 User) .这也称为用户实体类。然后一个用于向 MVC (UserModel) 发送数据/从 MVC 接收数据,数据在两者之间来回复制。这是一种非常常见的模式,例如见cpratt.co/entities-are-not-models
    【解决方案3】:

    我创建 ViewModel 调用 UserViewModel

     public class UserViewModel
        {
        //store DB for record
            public UserClass userClass { get; set; }
        //store Attribute class for validating boolean values
            public AttributeClass attributeClass { get; set; }
    
        }

      Controller
    
        private readonly ApplicationUserClass _auc;
    public abcController(ApplicationUserClass auc)
    {
        _auc = auc;
    }
    
    public IActionResult Index()
    {
        return View();
    }
    
    public IActionResult Create()
    {
        return View();
    }
    
                [HttpPost]
                [ValidateAntiForgeryToken]
                public IActionResult Create(UserClass uc)
                {
                    UserViewModel userViewModel = new UserViewModel() {
                      if (!ModelState.IsValid)
                        return View(uc);
    
                    }
                 
    
                    _auc.Add(uc);
                    _auc.SaveChanges();
                    return View();
                }
            }
    
    
    
    i don't know how to modify the controller logic. anybody can give advice? thanks

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 2022-06-10
      • 2013-02-15
      • 1970-01-01
      • 2020-11-22
      • 2022-12-01
      相关资源
      最近更新 更多