在模态窗口中的部分视图中提交后错误检查

时间:2013-11-21 18:42:09

标签: ajax asp.net-mvc jquery asp.net-mvc-4 kendo-ui

我有一个模态窗口,在按钮单击时弹出,包含一个带有几个字段和提交按钮的局部视图。在提交时,我将部分视图中的数据添加到数据库中,并重定向到生成弹出窗口的原始视图。所有这一切都很好。但是,现在我想在控制器操作中进行错误检查(对于唯一性)并从模态视图中显示错误。

以下是我如何使用其中的局部视图设置模态窗口

@Html.Kendo().Window().Name("CopyTaskWindow").Title("Copy Task").Modal(true).Width(400).Draggable().Iframe(false).Visible(false)

function onCopyClick(id) {
        var wnd = $("#CopyTaskWindow").data("kendoWindow");

        wnd.refresh({
            url: '@(Url.Action("CopyTaskRender", "Task"))',
            data: { id: id },
            iframe: true
        });
        wnd.center().open();
    }

这是部分视图

model pManager.Models.CopyTaskModel
    @using (Html.BeginForm("CopyTask", "Task", FormMethod.Post, new { id = "copyTaskForm" }))
    {
        @Html.HiddenFor(model=>model.TaskID)
        <div style="float: left; width: 48%;">
            <div class="editor-label">
                @Html.LabelFor(model => model.NewTaskName)
            </div>
            <div class="editor-field">
                @(Html.EditorFor(model=>model.NewTaskName))
            </div>
         </div>
    <div style="float: left; width: 48%;">
            <div class="editor-label">
                            @Html.LabelFor(model => model.ProjectId)
                </div>
            <div class="editor-field">
                                @(Html.Kendo().DropDownListFor(model => model.ProjectId) 
                                .DataTextField("Name") 
                                .DataValueField("ID") 
                                .DataSource(ds => ds 
                                    .Read("GetProjectsList", "Project").ServerFiltering(true) 
                                    ) 
                                ) 
            </div>
     </div>
    <div align="center" class="btns-container">
          <a class="k-button k-button-icontext k-grid-update btn-update" href="#" onclick="$('#copyTaskForm').submit()" >
                    <span class="k-icon k-update"></span>
                    Copy Task
                </a>
                <a class="k-button k-button-icontext k-grid-cancel btn-cancel" href="#">
                    <span class="k-icon k-cancel"></span>
                    Cancel
                </a>
        </div>
 }

这里是渲染函数和实际处理来自提交的局部视图的数据的函数

 public ActionResult CopyTaskRender(int? id)
        {
            var context = new pcloudEntities();
            var tmp = context.Tasks.Where(i => i.id == id).Select(task => new CopyTaskModel()
            {
               NewTaskName = task.Name,
               TaskID = task.id,
               ProjectId = task.ProjectId
            }).FirstOrDefault();
            return PartialView("CopyTask", tmp);
        }

        public ActionResult CopyTask(CopyTaskModel model)
        {
            var context = new pcloudEntities();

            var task = context.Tasks.FirstOrDefault(i => i.id == model.TaskID);
            if (isUnique(model.NewTaskName, model.ProjectId))
            {
                context.Detach(task);
                task.ProjectId = model.ProjectId;
                task.Name = model.NewTaskName;
                context.Tasks.AddObject(task);
                context.SaveChanges();
                return RedirectToAction("TasksList", "Task", new { projectID = model.ProjectId });
            }
            else
            {
                ModelState.AddModelError("", "Name is not unique");
                return PartialView("CopyTask", model);
            }
        }

正如您所看到的,我试图通过执行ModelState.AddModelError来返回错误。但是,模态窗口仍然会关闭,并在局部视图外部呈现模态窗口。

有人可以建议我如何实现从模态视图弹出的错误吗?

谢谢

1 个答案:

答案 0 :(得分:3)

你不能这样做。您需要使用远程验证。这是你如何做到的。

您可以像这样(更新)

定义您的剑道窗口
@Html.Kendo().Window().Name("CopyTaskWindow")
    .Title("Copy Task")
    .Modal(true).Width(400)
    .Draggable().Iframe(false)
    .Visible(false)
    .Events(events => events.Refresh("onRefresh")) // add a new event here...

function onRefresh(e) {
    // this is to make sure client validation works in the window...
    $.validator.unobtrusive.parse($("#CopyTaskWindow"));        
    // UPDATE: This will cause the validation to occur only on submit. 
    // But, as I explained in the comments, it won't work for remote validation...
    $.validator.setDefaults({
        onkeyup: false,
        onfocusout: false,
        onsubmit: true
    });

    var form = $("#CopyTaskWindow").find('#copyTaskForm');
    form.submit(function () {
        if (form.validate().valid()) {
            var wnd = $("#CopyTaskWindow").data("kendoWindow");
            wnd.close();
        }
    });
}

然后,在你的模型中,你在属性上使用RemoteAttribute,需要对此进行唯一性验证(我假设NewTaskName必须是唯一的,即使从你的代码中还不清楚是什么你想这样做):

public class CopyTaskModel
{
    [Remote("IsUnique", "YourControllerName", ErrorMessage = "The Task Name already exists.")]
    public string NewTaskName { get; set; }
    public int TaskID { get; set; }
    public int ProjectId { get; set; }
}

然后,将验证错误消息添加到部分视图:

@model pManager.Models.CopyTaskModel
@using (Html.BeginForm("CopyTask", "Task", FormMethod.Post, new { id = "copyTaskForm" }))
{
    @Html.HiddenFor(model=>model.TaskID)
    <div style="float: left; width: 48%;">
        <div class="editor-label">
            @Html.LabelFor(model => model.NewTaskName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NewTaskName)
            @Html.ValidationMessageFor(model => model.NewTaskName)
        </div>
     </div>

     // The rest of your Partial View... 
 } 

而且,在您的控制器中,您将拥有:

[HttpPost]
public ActionResult CopyTask(CopyTaskModel model)
{
    var context = new pcloudEntities();

    var task = context.Tasks.FirstOrDefault(i => i.id == model.TaskID);

    context.Detach(task);
    task.ProjectId = model.ProjectId;
    task.Name = model.NewTaskName;
    context.Tasks.AddObject(task);
    context.SaveChanges();

    return RedirectToAction("TasksList", "Task", new { projectID = model.ProjectId });
}

并且,新的远程验证操作:

public ActionResult IsUnique(NewTaskCopy model)
{
    var isUnique = IsUnique(model.NewTaskName, model.ProjectId);

    return Json(isUnique, JsonRequestBehavior.AllowGet);
}