【问题标题】:mvc submit form partialview in jquery modal duplicating formmvc在jquery模式复制表单中提交表单部分视图
【发布时间】:2014-08-29 15:25:00
【问题描述】:

我按照 Darin Dimitrov 的示例在模态对话框中提交了一个表单(带有验证):

Using Ajax.BeginForm with ASP.NET MVC 3 Razor

它在异常情况下完美运行。当我提交带有故意错误的表单时,我最终会在对话框中得到两份表单副本:

这是我的部分观点:

@model MvcAppTemplate.ViewModels.SupportClass1ViewModel
<script src="~/Scripts/Jquery/jquery.validate.min.js"></script>
<script src="~/Scripts/Jquery/jquery.validate.unobtrusive.js"></script>
<script>
    $(document).ready(function () {
        $('#SupportClass1Name').focus();

        $('form').submit(function () {
            if ($(this).valid()) {
                $.ajax({
                    url: this.action,
                    type: this.method,
                    data: $(this).serialize(),
                    success: function (result) {
                        $('#result').html(result);
                    }
                });
            }
            return false;
        });
    });
</script>
<div id="result"></div>
@using (Html.BeginForm("CreateDialog", "SupportClass1", FormMethod.Post, new { @class = "form-horizontal" }))
{
    @Html.AntiForgeryToken() 
    @Html.ValidationSummary(true, "The following errors occurred:", new { style = "color: red" })
    <fieldset>
        <legend>MyMainClass1</legend>
        @Html.ValidationMessage("CustomError", new { @class = "error" })
        @Html.HiddenFor(model => model.IsNew)
        <div class="form-group">
            <div class="col-lg-3 control-label">
                @Html.LabelFor(model => model.SupportClass1Name)
            </div>
            <div class="col-lg-6">
                @Html.TextBoxFor(model => model.SupportClass1Name, new { style = "width: 400px;", @maxlength = "50" })
                @Html.ValidationMessageFor(model => model.SupportClass1Name)
            </div>
        </div>
        <div class="form-group">
            <div class="col-lg-3 control-label">
                @Html.LabelFor(model => model.Active)
            </div>
            <div class="col-lg-6">
                @Html.EditorFor(model => model.Active, new { style = "width: 150px;" })
                @Html.ValidationMessageFor(model => model.Active)
            </div>
        </div>
        <p>
            <input type="submit" value="Create" class="btn btn-primary" />
            @Html.ActionLink("Cancel", "Search", "SupportClass1", null, new { @class = "btn btn-default" })
        </p>
    </fieldset>
}

我调用模态的视图:

@model MvcAppTemplate.ViewModels.SupportClass1ViewModel

@{
    ViewBag.Title = "Test";
}
<link href="~/Scripts/jquery-ui-1.11.1.custom/jquery-ui.min.css" rel="stylesheet" />
<link href="~/Content/dataTables.bootstrap.css" rel="stylesheet" />
<script src="~/Scripts/jquery-ui-1.11.1.custom/jquery-ui.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $('#dialog').dialog({
            autoOpen: false,
            width: 600,
            height: 400,
            resizable: true,
            title: 'Support Class 1',
            modal: true,
            open: function (event, ui) {
                $(this).load("@Url.Action("CreateDialog", "SupportClass1")");
             },
             buttons: {
                 "Close": function () {
                     $(this).dialog("close");
                 }
             }
         });
        $("#opener").click(function () {
            $("#dialog").dialog("open");
        });
    });
</script>

<div id="dialog" title="Create" >Please wait</div>
<button id="opener">Show Class</button>

最后是我的控制器:

// create in a pop up dialog
public ActionResult CreateDialog()
{
    var lvm = new SupportClass1ViewModel
    {
        IsNew = true,
    };
    return PartialView("_CreateDialog",lvm);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateDialog(SupportClass1ViewModel lvm)
{
    SupportClass1 supportClass1 = new SupportClass1();
    // Use Injector to handle mapping between viewmodel and model
    supportClass1.InjectFrom(lvm);

    try
    {
        if (ModelState.IsValid)
        {
            supportClass1Service.CreateSupportClass1(supportClass1);
            // redirect to the myMainClass1 view
            //return RedirectToAction("Details", "SupportClass1", new { id = supportClass1.SupportClass1Id });
            return Content("Thanks", "text/html");

        }
    }
    catch (DataException de)
    {
        //Log the error (add a variable name after DataException)
        var s = de.InnerException.ToString();

        ModelState.AddModelError("CustomError", "Unable to save changes. Try again, and if the problem persists, see your system administrator. Error: " + s);
    }
    // rehydrate the view
    lvm.IsNew = true;
    //return Content("Thanks", "text/html");
    return PartialView("_CreateDialog", lvm);

出现错误时,局部视图似乎被加载了两次:一次在结果 div 中,一次来自原始 @using Html.BeginForm()。我通过在结果 div 周围放置可见边框来验证这一点。

感谢任何帮助。

【问题讨论】:

    标签: asp.net-mvc twitter-bootstrap jquery-ui-dialog asp.net-mvc-viewmodel


    【解决方案1】:

    我想出了一个解决办法。正如我在评论中所说,我将部分视图的形式包装在一个 div 中:

    <div id="myForm">
    @using (Html.BeginForm("CreateDialog", "SupportClass1", FormMethod.Post, new { @class = "form-horizontal" }))
    {
    some content...
    }
    </div>
    

    然后,在我的 jquery 表单提交函数中,我清除了 div,然后用控制器的部分视图重新填充它(有验证错误的那个:

    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    $('#myForm').html('');
                    $('#result').html(result);
                }
            });
        }
        return false;
    });
    

    【讨论】:

      【解决方案2】:

      这一行是问题:

      success: function (result) {
                          $('#result').html(result);
                      }
      

      这个处理程序在成功和失败两种情况下都会被调用,所以最终表单会显示两次,一次来自原始渲染,然后在发生错误时显示在结果 div 中。

      将您的控制器代码更改为:

       try
      {
          if (ModelState.IsValid)
          {
              supportClass1Service.CreateSupportClass1(supportClass1);
              // redirect to the myMainClass1 view
              //return RedirectToAction("Details", "SupportClass1", new { id = supportClass1.SupportClass1Id });
              return Json(new {success = true, message ="Thanks" } );
      
          }
      }
      catch (DataException de)
      {
          //Log the error (add a variable name after DataException)
          var s = de.InnerException.ToString();
      
          ModelState.AddModelError("CustomError", "Unable to save changes. Try again, and if the problem persists, see your system administrator. Error: " + s);
      }
      
      return Json(new {success = "false", message = "Error"}); // do a concatenation of the model state errors
      

      那么你的成功处理器可能看起来像

       success: function (result) {
                          if(result.success) {
                              $('#result').html(result.message);
                          }
                          else {
                              // provide some highlighting or what have you or just set the message
                              $('#result').addClass("error").html(result.message);
                          }
                      }
      

      【讨论】:

      • 感谢您的快速回复!您的建议消除了重复,但我在表单上使用了不显眼的验证(由图像中的读取文本指出),这似乎绕过了。如果可能的话,我更愿意坚持使用验证表单,而不是列出来自控制器的错误。
      • 我设法让它工作。我所做的是将我的 Html.BeginForm() 包装在一个单独的 div 中,并在成功函数中清除 div。我还没有把它作为答案,因为我需要对其进行全面测试。
      猜你喜欢
      • 2011-09-21
      • 2011-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-11
      • 1970-01-01
      相关资源
      最近更新 更多