Jquery dialog and partial view with IValidatableObject mvc3
I am using jquery dialog to show the details of my view for adding and editing issue
I was able to show the form and on the update button the first level of validation is working fine which is [Required]
and [RegularExpression(...)]
, but its not working on the model validation level (IValidatableObject
), the model is returning the errors but the form is not showing them.开发者_如何学JAVA
here is the jQuery
i am using
the controller
[HttpPost]
public ActionResult _Degree(TDegree degree)
{
if (ModelState.IsValid)
{
if (degree.Degree == 0)
{
db.TDegrees.Add(degree);
db.SaveChanges();
}
else
{
TryUpdateModel<TDegree>(degree);
}
return RedirectToAction("Index", "Profile");
}
// what should i return here to stay on the dialog form + returning the errors? i tried this way to show the errors but the errors not shown as html but string
return Content(ShowAllErrors());
}
private String ShowAllErrors()
{
StringBuilder sb = new StringBuilder();
TagBuilder ul = new TagBuilder("ul");
foreach (var e in ModelState.Values.Where(t => t.Errors.Count > 0))
{
foreach (var d in e.Errors)
{
TagBuilder li = new TagBuilder("li");
li.MergeAttribute("class", "field-validation-error");
li.SetInnerText(d.ErrorMessage);
sb.Append(li.ToString());
}
}
ul.SetInnerText(sb.ToString());
return ul.ToString();
}
the model
public partial class TDegree : IValidatableObject
{
// Primitive properties
public long Degree { get; set; }
public int Country { get; set; }
public long Applicant { get; set; }
[DisplayName("Degree Type")]
public short DegreeType { get; set; }
[Required]
public string Major { get; set; }
[Required]
public string Institution { get; set; }
[DisplayName("Completion Year")]
public short CompletionYear { get; set; }
[RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Email is not valid")]
public string Email { get; set; }
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
public bool IsEducation { get; set; }
// Navigation properties
public virtual TApplicant TApplicant { get; set; }
public virtual TCountry TCountry { get; set; }
public virtual TDegreeType TDegreeType { get; set; }
// this method is running after the attributes validations and its returning the errors correctly but they are not shown on the form!!
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (DegreeType == 0)
yield return new ValidationResult("Degree Type is required", new string[] { "DegreeType" });
if (CompletionYear < 1950 || CompletionYear > DateTime.Today.Year)
yield return new ValidationResult("Completion Year is out of range!", new string[] { "CompletionYear" });
}
}
the Index view
@Html.ImageLink("_Degree", "Profile", new { id = 0 }, @Url.Content("~/Content/images/add.png"), "Add", new { @class = "addLink" }, null)
<table>
<tr>
<th>
Country
</th>
<th>
Type
</th>
<th>
Major
</th>
<th>
Institution
</th>
<th>
Year
</th>
<th>
Email
</th>
<th>
Phone
</th>
<th>
</th>
</tr>
@foreach (var item in Model)
{
<tr class="row">
<td>
@Html.DisplayFor(modelItem => item.TCountry.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.TDegreeType.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Major)
</td>
<td>
@Html.DisplayFor(modelItem => item.Institution)
</td>
<td>
@Html.DisplayFor(modelItem => item.CompletionYear)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
@Html.ImageLink("_Degree", "Profile", new { id = item.Degree }, @Url.Content("~/Content/images/select.png"), "Edit", new { @class = "editLink" }, null)
</td>
</tr>
}
</table>
<div id="updateDialog" title="Degree Details">
</div>
<script type="text/javascript">
var linkObj;
$(function () {
$('#updateDialog').dialog({
autoOpen: false,
width: 590,
resizable: false,
modal: true,
buttons: {
"Update": function () {
$("#update-message").html('');
$("#updateDegreeForm").validate();
$("#updateDegreeForm").submit();
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
$(".editLink,.addLink").click(function () {
linkObj = $(this);
var dialogDiv = $('#updateDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data) {
dialogDiv.html(data);
var $form = $("#updateDegreeForm");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
$form.validate($form.data("unobtrusiveValidation").options);
dialogDiv.dialog('open');
});
return false;
});
});
function updateSuccess() {
if ($("#update-message").html() == "False") {
$("#update-message").css('display', 'block');
// here it working fine if the model attributes fired the errors
}
else {
// if the model attributes validations was correct and the model validation returned errors, this block will be executed
// i need here to show the errors of the model, and if there was no errors i will close the dialog
}
}
</script>
the details view ( partial view )
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Ajax.BeginForm("_Degree", "Profile", null,
new AjaxOptions
{
UpdateTargetId = "update-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "updateSuccess"
},
new { @id = "updateDegreeForm" }))
{
@Html.ValidationSummary()
<div id="update-message" class="display:none;">
</div>
<table>
<tr>
<td class="editor-label">
@Html.LabelFor(model => model.Major)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.Major)
</td>
<td class="editor-label">
@Html.LabelFor(model => model.Institution)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.Institution)
</td>
</tr>
<tr>
<td class="editor-label">
@Html.LabelFor(model => model.Country)
</td>
<td class="editor-field">
@Html.DropDownList("Country")
</td>
<td class="editor-label">
@Html.LabelFor(model => model.DegreeType)
</td>
<td class="editor-field">
@Html.DropDownList("DegreeType")
</td>
</tr>
<tr>
<td class="editor-label">
@Html.LabelFor(model => model.CompletionYear)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.CompletionYear)
</td>
<td class="editor-label">
@Html.LabelFor(model => model.Email)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.Email)
</td>
</tr>
<tr>
<td class="editor-label">
@Html.LabelFor(model => model.Phone)
</td>
<td class="editor-field">
@Html.EditorFor(model => model.Phone)
</td>
</tr>
</table>
}
how can i let the all levels of validation to be shown in the dialog form? thanks in advance
Well after wasting almost 2 days I stumbled upon a solution to the problem. The skeleton of what I am using for partial/jquery dialog is same as you are using (which I took from a blog post). I modified my Create
method as follows:
[HttpPost]
public JsonResult Create(EventObject evt)
{
if(ModelState.IsValid)
{
//save the model and return success
return new JsonResult{
Data = new
{
Result="S",
Message="successfully created event"
}
};
}
else
{
return new JsonResult{
Data = new
{
Result="E",
Message=CONVERT MODELSTATE TO STRING
}
};
}
}
Now on markup side I have following div:
<div id="create-event-error"></div>
my update function is as follows:
function updateSuccess(a) {
if (a.Result=="S") {
$("#update-message").html(a.Message).show().delay(3000).hide();
$dlg.dialog('close');
}
else {
var d=$("div#create-event-errors");
d.html(a.Message).dialog({
//VARIOUS DIALOG OPTIONS
});
}
}
In place of dialog you can show the errors anyway you like.
精彩评论