模型未通过验证

时间:2018-08-03 14:54:08

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

因此,即使我明确要求它有一个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完成的?

3 个答案:

答案 0 :(得分:3)

您的输入是:

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

答案 1 :(得分:1)

一个好的做法是在您的post方法上使用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很好。因此,您可以仅将viewmodel作为操作的参数发送。您可以按照以下步骤进行操作:

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

答案 2 :(得分:0)

因此,我找到了至少一个解决方案,但是潜在的问题仍然存在。 问题在于,即使某些模型无效,在控制器中,Modelstate.IsValid始终为true,因此在重定向到另一个页面之前,它只是执行我想要的操作。 解决方案是,如果我在控制器中检查字符串是否为null或为空,并且仅返回(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();
        }
    }