我有一个控制器有两个动作:
[AcceptVerbs("GET")]
public ActionResult Add()
{
PrepareViewDataForAddAction();
return View();
}
[AcceptVerbs("POST")]
public ActionResult Add([GigBinderAttribute]Gig gig, FormCollection formCollection)
{
if (ViewData.ModelState.IsValid)
{
GigManager.Save(gig);
return RedirectToAction("Index", gig.ID);
}
PrepareViewDataForAddAction();
return View(gig);
}
如您所见,当表单发布其数据时,Add操作使用GigBinder(IModelBinder的实现)
在这个活页夹中,我有:
if (int.TryParse(bindingContext.HttpContext.Request.Form["StartDate.Hour"], out hour))
{
gig.StartDate.Hour = hour;
}
else
{
bindingContext.ModelState.AddModelError("Doors", "You need to tell us when the doors open");
}
表单包含一个id为“StartDate.Hour”的文本框。
正如您在上面所看到的,GigBinder会测试用户是否在文本框中键入了一个id为“StartDate.Hour”的整数。如果没有,则使用AddModelError将模型错误添加到模型状态。
由于gigs属性gigs.StartDate.Hour是强类型的,因此如果用户在表单文本框中键入了这个值,我就无法将其值设置为“TEST”。
因此,我无法设置gigs.StartDate.Hour的值,因为用户输入的是字符串而不是整数。
由于Add Action返回视图并传递模型(返回View(gig);)如果modelstate无效,当表单重新显示验证消息时,值“TEST”不会显示在文本框中。相反,它将是gig.StartDate.Hour的默认值。
如何解决这个问题?我真的卡住了!
答案 0 :(得分:2)
我认为问题是你的ViewModel与你的View不够匹配。在MVC中,您的ViewModel尽可能与View匹配,这一点非常重要。
在ViewModel中,您假设一个整数,但在您的视图中,您使用TextBox渲染属性,这将允许任何类型的文本。这里存在不匹配的问题,并且您在尝试映射它们时遇到的困难是不匹配的症状。
我认为你应该: 1.将ViewModel属性的类型更改为字符串,然后在控制器中进行验证,以确保输入的字符串实际上是一个数字或: 2.将视图呈现的控件更改为仅允许通过自定义控件或Javascript验证输入数字的控件(如@Qun Wang建议的那样)
就个人而言,我建议使用选项1.这样ViewModel就不依赖于View实现。
答案 1 :(得分:1)
您可以在PrepareViewDataForAddAction方法中执行此操作吗?..
if (!ViewData.ModelState.IsValid)
{
ViewData["StartDate.Hour"] = "Error";
}
表单上的其他字段仍会根据Gig对象的属性进行填充。
答案 2 :(得分:1)
我认为您需要先进行一些基本的客户端验证。 不允许它发布到服务器。