我已经有一段时间没有使用Umbraco了。目前正在建立一个Umbraco 7实例,它有很多表单。我正在努力正确地处理ModelState。希望有人能解释我做错了什么。最近几天我读了很多文章,看起来有很多方法可以做到这一点,但我所尝试的都不适合我。我来解释一下我现在在哪里。
使用Ditto返回强类型页面模型的页面控制器:
public override ActionResult Index(RenderModel model)
{
var customModel = model.Content.As<MyCustomPage>();
// Init the model that I want to bind to the form
ViewBag.EditFormModel = new EditFormModel()
{
MyProperty = "init value"
};
return this.CurrentTemplate(customModel);
}
我的表单模型:
public class EditFormModel
{
public int Id { get; set; }
[System.ComponentModel.DisplayName("Label")]
[System.ComponentModel.DataAnnotations.Required]
public string MyProperty{ get; set; }
}
在我看来:
@{
// Get the model returned after postback if available, otherwise the initialised model
var editFormModel = TempData["EditFormModel"] as LocationEditFormModel ?? ViewBag.EditFormModel as LocationEditFormModel;
}
@Html.Partial("CustomEditForm", editFormModel)
那个局部视图:
@model EditFormModel
@using (Html.BeginUmbracoForm("PostForm", "PostFormSurface", FormMethod.Post))
{
@Html.ValidationSummary(false, string.Empty)
@Html.AntiForgeryToken()
@Html.EditorFor(m => m.MyProperty)
<input type="submit" class="btn btn-primary" value="Submit" />
}
我的表面控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PostForm(LocationSearchFormModel model)
{
bool passesServerSideValidation = this.Validate(model);
if (passesServerSideValidation)
{
// Save and perform a redirect
}
else
{
// I read something that suggested I should clear model state here but it doesn't seem to make a difference
ModelState.Clear();
ModelState.AddModelError(string.Empty, "Not valid");
}
// Add the model to temp data so we can retain values on postback
TempData["SearchFormModel"] = model;
return CurrentUmbracoPage();
}
问题是,当我提交表单时,在我点击return CurrentUmbracoPage();
行时,我可以观察到ModelState.IsValid
如我所料为假。但是,当我逐步执行时,下一行命中的是页面控制器中的Index方法。马上ModelState.IsValid
就成立了。因此,当表单重新加载时,我的验证摘要不会显示。
所以很明显我在这里做错了什么,但是我读到的东西都没有给我指明正确的方向。谢谢你的建议。
找到解决办法了
在我的设置中,我有一个通过RenderMvcController子类型渲染的表单。它的模型继承自RenderModel。
我发布到一个SurfaceController子类型。这个模型不能继承RenderModel,因为它需要IPublishedContent,这在post中是不可用的。
当有验证错误的问题是,我需要做我的RenderMvcController做什么,基于模型的SurfaceController得到,而不离开控制器的上下文持有ModelState。
我发现SurfaceController拥有一个属性CurrentPage,它是构建RenderModel实例来渲染视图所需的IPublishedContent。在不离开Controller上下文的情况下呈现视图将使视图可以使用ModelState。
Umbraco(或MVC)甚至足够聪明地重用发布的值,而不需要在代码中复制它们。
现在做一个完整的代码示例是太多的工作。我来分享一下SurfaceController上的动作。(或者更确切地说,是它的匿名版本。)
[HttpPost]
public ActionResult Index(MySurfaceControllerModel model)
{
if (!ModelState.Isvalid)
{
return View("MyView", new MyRenderModel(CurrentPage));
}
// Do some stuff with my valid model.
return RedirectToAction("thenextpage");
}
我们基本上做的是返回CurrentUmbracoPage()当表单是无效的,只是执行RedirectToCurrentUmbracoPage()当它是有效的,它不需要保持值重新张贴表单为例。我们使用ModelState来检查模型是否有效。
你的代码可以简化成这样:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PostForm(LocationSearchFormModel model)
{
if (ModelState.IsValid == false || !this.Validate(model))
return CurrentUmbracoPage();
TempData["SearchFormModel"] = model;
return RedirectToCurrentUmbracoPage();
}
没有经过测试,但它可能会帮助您处理这个问题