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