MVC中的模态编辑

时间:2012-06-05 13:19:52

标签: c# ajax asp.net-mvc devexpress modal-dialog

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

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

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

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

- 编辑页面 - 只是部分视图 - 工作得很好。 我创建了一个小测试页面,其中包含一个文本框,它带有一个小数。

我想使用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。

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

这是onComplete事件:

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

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

这就是问题1号

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

这是问题2:)

另外,如果你知道一个更好的方法来解决这个问题,请不要犹豫回应(因为这种方法看起来真的很复杂 - 它应该做什么 - )

对于冗长的帖子感到抱歉,但我希望一切都很清楚。

感谢您的帮助&amp;时间!

1 个答案:

答案 0 :(得分:4)

我之前使用过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应用程序运行,并且所有导航/验证等将“正常工作”。

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