【问题标题】:Model isn't validating模型未验证
【发布时间】:2019-01-11 12:04:50
【问题描述】:

因此,在为我的模型输入文本时,它始终有效,即使我明确要求它具有 minLength,尽管它为空或小于 minLength。

型号:

public class CommentaarCreate_VM
{
    public Stad Stad { get; set; }
    [Required]
    public Commentaar Commentaar { get; set; }
}
public class Commentaar
{
    [Key]
    public int CommentaarId { get; set; }
    [Required]
    public string UserId { get; set; } 
    [Required]
    public int StadId { get; set; }
    [Required(AllowEmptyStrings=false, ErrorMessage="You need to enter a comment of valid length")]
    [MinLength(5, ErrorMessage ="You need to enter a comment of valid length")]
    public string CommentaarText { get; set; }
    [Required]
    [DataType(DataType.DateTime)]
    public DateTime Tijdstip { get; set; }
}

查看:

@model DataGent.Web.ViewModels.CommentaarCreate_VM

@{
ViewData["Title"] = "Create new comment";
}
<div class="row">
<div class="col-md-4">
    <form asp-action="Create">
        <div asp-validation-summary="All" class="text-danger"></div>
        <input type="hidden" asp-for="Stad.Id" />
        <input type="hidden" asp-for="Stad.Naam" />
        <input type="hidden" value="@Html.AntiForgeryToken()" />

        <div class="form-group">
            <label asp-for="Commentaar" class="control-label"></label>
            <input asp-for="Commentaar" class="form-control" />
            <span asp-validation-for="Commentaar.CommentaarText" class="text-danger"></span>
        </div>
        <div class="form-group">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </form>
</div>

控制器动作:

public ActionResult Create(int id)
    {
        CommentaarCreate_VM vm = new CommentaarCreate_VM()
        {
            Stad = _dataGentService.GetStadFromId(id),
            Commentaar = null
        };

        return View(vm);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind("CommentaarText, Tijdstip")] int id, IFormCollection collection) //Bind = protect from overposting
    {
        try
        {
            // Creating  object to POST
            Commentaar commentaar = new Commentaar
            {
                UserId = _userManager.GetUserId(HttpContext.User),
                StadId = id,
                CommentaarText = collection["Commentaar"],
                Tijdstip = DateTime.Now
            };

            var result = _dataGentService.PostCommentaar(commentaar);

            return RedirectToAction(nameof(Index));
        }
        catch
        {
            return View();
        }
    }

我有什么遗漏吗?我以为除了数据注释之外的所有工作都是由 MVC 完成的?

【问题讨论】:

  • 在appsetting下的web.config中检查ClientValidationEnabledUnobtrusiveJavaScriptEnabled是否设置为true
  • 你说的是客户端验证还是服务器端?在服务器端,您永远不会检查 ModelState.IsValid。你怎么知道你的模型状态是否有效?
  • @Fran 客户端验证。
  • @SuprabhatBiswal web.config 显然在这个版本的 ASP 中不再存在,我确实尝试通过 startup.cs 服务手动启用它,但这并没有改变,所以我猜它是开启的默认情况下。

标签: c# asp.net asp.net-mvc validation model


【解决方案1】:

您的输入是:

<input asp-for="Commentaar" class="form-control" />

您必须将 asp-for 从 Commentaar 更改为 Commentaar.CommentaarText 以便验证:

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

更新:

在将视图模型中的 Commentaar 对象传递给视图之前对其进行初始化:

public ActionResult Create(int id)
{
    CommentaarCreate_VM vm = new CommentaarCreate_VM()
    {
        Stad = _dataGentService.GetStadFromId(id),
        Commentaar = new Commentaar()
    };

    return View(vm);
}

【讨论】:

  • 试过了,但没用。我做了一个新的测试 Create View,默认情况下所有属性都做了这一切,但即使所有属性都 [required] 作为 dataAnnotation,它仍然永远不会出错。
  • @Sven0567 你能在你的发布动作中从客户端获取输入值吗?
  • @Sven0567 请问你为什么使用绑定,而不是仅仅返回 CommentaarCreate_VM 对象?
  • 是的,我可以从 post 操作中获取输入值,我可以手动完成这一切,但我只是感到困惑,为什么它不应该自动执行此操作。另外,我用 bind 表示只有这 2 个道具应该被更改以防止过度发布。
【解决方案2】:

一个好的做法是在您的发布方法上使用ModelState.IsValid,以便检查正在发送的模型的属性。也就是说,ModelState.IsValid 检查您在模型上编写的数据注释。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind("CommentaarText, Tijdstip")] int id, IFormCollection collection) //Bind = protect from overposting
    {
         if(ModelState.IsValid)
         {
             //If it is valid, do all your business logic, like creating a new entry.
         }
         else
         {
             //Handle it
             return View();
         }
    }

另一件事是我看到你使用ViewModels,这很好。因此,您可以将您的视图模型作为您的操作的参数发送。你可以这样做:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(CommentaarCreate_VM viewmodel)
    {
          if(ModelState.IsValid)
          {
               //It is valid
               //All your logic
          }
          else
          {
               //Not valid
               return View(Viewmodel model)
          }         
    }

通过这样做,您必须将数据注释添加到CommentaarCreate_VM

  public class CommentaarCreate_VM
    {
        public Stad Stad { get; set; }
        [Required(AllowEmptyStrings=false, ErrorMessage="You need to enter a comment of valid length")]
        [MinLength(5, ErrorMessage ="You need to enter a comment of valid length")]
        public Commentaar Commentaar { get; set; }
    }

【讨论】:

  • 感谢您的提示,我尝试将注释添加到视图模型,但这也没有用,ModelState.IsValid 始终返回 true,即使视图中的输入值为空并且该属性有一个 [Required] 标签。
  • 也许这听起来很棘手,但是您是否尝试过清理您的解决方案并重新构建它?实际上,我经常遇到这种情况,在我清理整个解决方案并重新构建它之前,我的模型上的更改(例如对其属性的新数据注释)都没有计算在内。
  • 清理重建,之前忘记做了,但遗憾的是它仍然没有改变任何东西。
【解决方案3】:

所以我至少找到了一些解决方案,但根本问题仍然存在。 问题是在控制器中 Modelstate.IsValid 始终为真,即使某些模型不应该是有效的,所以它只是在重定向到另一个页面之前执行我想要的操作。 解决方案是,如果在控制器中检查字符串是否为空或为空,则我可以使错误消息正常工作,如果是,则只需 Return(viewmodel),这样就可以使错误消息正常工作。 显然,Modelstate.IsValid 应该返回 true,我仍然不知道为什么会这样。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind("CommentaarText, Tijdstip")] int id, CommentaarCreate_VM viewModel, IFormCollection collection) //Bind = protect from overposting
    {
        try
        {
          //If incoming string is null or empty
            if (string.IsNullOrEmpty(collection["Commentaar"]))
            {
                return View(viewModel);
            }
//This always returns true. It really shouldn't, because otherwise I wouldn't need that earlier check. 
//If the model isn't valid in the View, this one should be false, right?
            if (ModelState.IsValid)
            {
                // Creating  object to POST
                //.....

                return RedirectToAction(nameof(Index));
            }

            return View();
        }
        catch
        {
            return View();
        }
    }

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多