我一直在寻找一种使用模式弹出窗口更新数据的方法。 现在我正在使用 devexpress,因为我们已经在使用其他 devexpress 控件(但如果 jquery 库更容易的话,这可能会改变!!)
我陷入了验证方面。坦率地说,对于我想要实现的目标来说,整个过程似乎相当困难。
无论如何,让我描述一下我目前已经制定的流程:
-索引页包含可更新的不同元素的概述。使用 HtmlExtension,我能够创建一个 devexpress 弹出窗口,当您打开弹出窗口时,它会加载编辑页面。 => @Html.PopupControl().WithText("编辑").PopupGoesTo(Url.Action("EditPopup"等)
-编辑页面-这只是部分 View -工作得很好。 我创建了一个小测试页面,其中包含 1 个文本框,其中包含小数。
我想使用ajax提交表单(因为坦率地说,我不知道如果我进行完整的回发,我不知道如何显示验证,因为我需要能够创建弹出窗口并将数据绑定(bind)到它并且触发验证错误)。
<script type="text/javascript">
function EndPopUpUpdate(message) {
if (message.url) {
window.locatin.href = url;
}
$("#submitButtonPopUp, #loadingPopUp").toggle();
}
function BeginPopUpUpdate() {
$("#submitButtonPopUp, #loadingPopUp").toggle();
}
</script>
using (Ajax.BeginForm("Edit", "xxx", new AjaxOptions { UpdateTargetId = "PopUpDiv", HttpMethod = "Post", OnBegin = "BeginPopUpUpdate", OnComplete = "EndPopUpUpdate"}, new { id = "PopUpForm" }))
{
<div id="PopUpDiv">
@Html.Partial("EditPopup", new xxxViewModel())
</div>
}
当我通过手动重新 Hook jquery 事件回发时,我能够实现验证(因为这些事件不会被 Hook ,因为页面是动态加载的)
function ReconnectValidation() {
$("#PopUpForm").ready(function () {
$.validator.unobtrusive.parse("#PopUpForm");
});
$("#submitButton").click(function (e) {
var form = $("#PopUpForm");
if (!form.valid()) {
e.preventDefault();
}
});
}
所以这处理了我的客户端验证,这是有效的。
现在,我的实际问题!服务器端验证。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([ModelBinder(typeof(CommandModelBinder))] UpdateCommand command)
{
if (!ModelState.IsValid)
{
//using the command pattern
var handlerResult = HandlerLocator.GetQueryHandler<IGetOverviewHandler>().Execute(..);
return PartialView("EditPopUp", handlerResult.ViewModel);
}
HandlerLocator.GetCommandHandler<UpdateCommand>().Handle(command);
var returnLink = Url.Action("Index", new {..});
return Json(new { url = returnLink }, JsonRequestBehavior.AllowGet);
}
我编写了一个 CustomModelBinder,它除了在我的命令对象(如果你愿意的话,我的返回模型)中查找属性并在 formcollection 中查找是否可以找到具有相同名称的匹配对象之外什么也不做。然后它尝试转换它,如果失败,它会将 ModelError 绑定(bind)到我的 ModelState。
所以,现在我们有一个 ModelState,它要么有效,要么无效。 如果它有效,我想重定向到索引(以便我的概述可以更新)。我读过我应该在客户端处理这个问题,因为 ajax.BeginForm 将取代 "PopUpDiv"-div 与结果(它只是在我的页面中创建相同的页面)。
这是 onComplete 事件:
function EndPopUpUpdate(message) {
if (message.url) {
window.locatin.href = url;
}
$("#submitButtonPopUp, #loadingPopUp").toggle();
}
问题是,我没有收到 json 消息,但收到了 PartialView。 这意味着我无法访问 message.url..因为这不是我收到的:/
这就是问题 1
如果对象无效,我想返回带有模型的部分 View 并向用户提供错误。 当我返回分部 View 时,它只是替换当前 View ,但不会显示任何验证错误..
这是问题 2 :)
此外,如果您知道解决此问题的更好方法,请随时回复(因为此方法对于它所做的或应该做的事情来说似乎非常复杂)
很抱歉这篇文章很长,但我希望一切都清楚。
感谢您的帮助和时间!
最佳答案
我之前使用过 jQuery UI () 的对话框插件,我发现它效果很好。我通常会在弹出窗口中的 iframe 中打开链接,这避免了您描述的问题,因为页面是动态加载的,所以 jQuery 验证事件没有被连接 - 客户端和服务器端验证都应该正常工作,就在此 iframe 内。
这种技术的好处是,您可以像平常一样在索引页面中生成操作链接,只需向其中添加一类弹出窗口即可,例如
@Html.ActionLink("Edit", "Edit", new { id = Model.Id }, new { @class = "popup" })
然后,您可以使用 jQuery 在对话框 iframe 中打开这些链接,如下所示:
$("a.popup").click(function(e) {
e.preventDefault();
$("<iframe />").attr("src", $(this).attr("href") + "?popup=true").dialog({ show: "fadeIn", modal: true, width: 300, height: 300});
});
这基本上会查找弹出链接,取消默认行为(页面导航)并在弹出窗口内的 iframe 中打开该 URL,添加一个查询字符串来标识该页面位于弹出窗口内。这个查询字符串的原因并知道它是一个弹出窗口,允许您在 View 中加载不同的布局页面,也许通过操作过滤器,例如:
public class Popup : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result != null
&& filterContext.Result is ViewResult
&& filterContext.RequestContext.HttpContext.Request["popup"] == "true")
(filterContext.Result as ViewResult).MasterName = "~/Views/Shared/_PopupLayout.cshtml";
}
}
这意味着您可以轻松地将此属性应用于您想要应用操作方法的类。此方法还意味着,如果您将来改变主意(即删除弹出窗口),那么您可以轻松删除取消点击的 jQuery,并且您的应用程序将继续作为具有单独页面的普通 MVC 应用程序运行,并且所有内容导航/验证等将“正常工作”。
我希望一切都有意义并且有帮助。
关于c# - MVC 中的模态编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10898086/