MVC 中的模态编辑



我一直在寻找一种使用模式弹出窗口更新数据的方法。现在我正在使用 devexpress,因为我们已经在使用其他 devexpress 控件(但如果 jquery 库更容易,这可能会改变!!

被困在验证方面。坦率地说,整个过程对于我想要实现的目标来说似乎很困难。

无论如何,让我描述一下我目前制定的过程:

-索引页面包含可以更新的不同元素的概述。使用 HtmlExtension,我能够创建一个 devexpress 弹出窗口,当您打开弹出窗口时加载编辑页面。=> @Html.PopupControl()。WithText("编辑")。PopupGoesTo(Url.Action("EditPopup", etc

-编辑页面 - 只是一个部分视图 - 工作正常。我创建了一个小测试页面,其中包含 1 个文本框,其中包含一个小数点。

我想使用 ajax 提交表单(因为坦率地说,如果我进行完整的回发,我不知道如何显示验证,因为我需要能够创建弹出窗口并将数据绑定到它并触发验证错误)。

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

当我回发时,我能够通过手动重新挂钩 jquery 事件来实现验证(因为这些事件不会被挂钩,因为页面是动态加载的)

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绑定到我的ModelState。

所以,现在我们有一个有效或无效的模型状态。如果它有效,我想重定向到索引(以便我的概述可以更新)。我已经读到我应该在客户端处理这个问题,因为 ajax。BeginForm 将取代"PopUpDiv"-div 与结果(它只是在我的页面中创建相同的页面)。

以下是 onComplete 事件:

function EndPopUpUpdate(message) {
            if (message.url) {
                window.locatin.href = url;
            }
            $("#submitButtonPopUp, #loadingPopUp").toggle();
        }

问题是,我没有收到 json 消息,但我收到 PartView。这意味着我无法访问 message.url..因为那不是我收到的:/

所以这是第一个问题

如果对象无效,我想返回带有模型的分部视图并向用户提供错误。当我返回分部视图时,它只是替换当前视图,但它没有显示任何验证错误

这是问题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,添加一个查询字符串来标识页面是否在弹出窗口中。此查询字符串的原因以及知道它是一个弹出窗口允许您在视图中加载不同的布局页面,可能通过操作过滤器,例如:

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 应用程序运行,并且所有导航/验证等将"正常工作"。

我希望一切都有意义并有所帮助。

最新更新