I followed Darin Dimitrov's example to submit a form (with validation) in a modal dialog:
Using Ajax.BeginForm with ASP.NET MVC 3 Razor
It works perfectly with on exception. When I submit the form with intentional errors, I end up with two copies of the form in the dialog:
Here is my partial view:
@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>
}
The view I call the modal from:
@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>
And finally my controller:
// 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);
It appears the partial view is loaded twice when there is an error: once in the result div and once from the original @using Html.BeginForm(). I verified this by putting a visible border around the result div.
Any help is appreciated.
I figured out a fix. As I said in my comment, I wrapped my partial view's form in a div:
<div id="myForm">
@using (Html.BeginForm("CreateDialog", "SupportClass1", FormMethod.Post, new { @class = "form-horizontal" }))
{
some content...
}
</div>
Then, in my jquery form submit function, I cleared the div before repopulating it with the partial view form the controller (the one with the validation errors:
$('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;
});