Facing issue while showing the error messages in P

2019-07-14 04:29发布

问题:

Following is my Area in MVC3

Model

public class AdminModule
{
    [Display(Name = "My Name")]
    [Required]
    public String MyName { get; set; }
}

Partial View

@model _1.Areas.Admin.Models.AdminModule
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myForm" }))
{
    @Html.LabelFor(i => i.MyName)
    @Html.TextBoxFor(i => i.MyName)
    @Html.ValidationMessageFor(i => i.MyName)
    <p id="getDateTimeString">
    </p>
    <input type="submit" value="Click here" id="btn" />
}

<script language="javascript" type="text/javascript">
    $('#btn1').click(function () {
        debugger;
        var $form = $("#myForm");

        // Unbind existing validation
        $form.unbind();
        $form.data("validator", null);

        // Check document for changes
        $.validator.unobtrusive.parse(document);

        // Re add validation with changes
        $form.validate($form.data("unobtrusiveValidation").options);

        if ($(this).valid()) {
            var url = '@Url.Action("Index_partialPost", "Admin", 
                                                new { area = "Admin" })';
            $.post(url, null, function (data) {
                alert(data);
                $('#myForm').html(data);
            });
        }
        else

        return false;
    });
</script>

Controller Action

[HttpPost]
public ActionResult Index_partialPost(AdminModule model)
{
    return PartialView("_PartialPage1", model);
} 

[HttpGet]
public ActionResult Index_partial()
{
    return PartialView("_PartialPage1");
}

Whenever I submit the form and leaves the required field empty. it goes to server i think. I checked here...

My confusion is => How can I modify my below mentioned code to display the same validation messages mentioned in model at client end using $.post ?

回答1:

You could enable unobtrusive client side validation. Start by adding the following script reference:

<script type="text/javascript" src="@Url.Content("~/scripts/jquery.validate.unobtrusive.js")"></script>

and then:

@model _1.Areas.Admin.Models.AdminModule
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myForm" }))
{
    @Html.LabelFor(i => i.MyName)
    @Html.TextBoxFor(i => i.MyName)
    @Html.ValidationMessageFor(i => i.MyName)
    <p id="getDateTimeString"></p>
    <input type="submit" value="Click here" />
}

<script type="text/javascript">
    $('#myForm').submit(function () {
        if ($(this).valid()) {
            $.post(this.action, $(this).serialize(), function(data) {
                $('#myForm').html(data);

                $('#myForm').removeData('validator');
                $('#myForm').removeData('unobtrusiveValidation');
                $.validator.unobtrusive.parse('#myForm');
            });
        }
        return false;
    });
</script>

UPDATE:

Now that you sent me your actual code by email I see that there are a hell lot of a problems with it. Instead of going through all of them I prefer to completely rewrite everything from scratch.

So we start by the ~/Areas/Admin/Views/Shared/_LayoutPage1.cshtml:

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        <ul>
            <li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, null)</li>
        </ul>
        @RenderBody()
    </div>
    <script src="/Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <script src="/Scripts/jquery.validate.js" type="text/javascript"></script>
    <script src="/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

Notice how I moved all scripts to the bottom of the file as well as added a specifically dedicated section where custom scripts will be placed.

Next we move to the ~/Areas/Admin/Views/Admin/Index.cshtml:

@model _1.Areas.Admin.Models.AdminModule
@{
    ViewBag.Title = "Index";
    Layout = "~/Areas/Admin/Views/Shared/_LayoutPage1.cshtml";
}

<div id="formContainer" data-url="@Url.Action("Index_partial", "Admin", new { area = "Admin" })"></div>
<input id="BTN" type="button" value="Button" />

@section Scripts {
    <script type="text/javascript" src="@Url.Content("~/areas/admin/scripts/myscript.js")"></script>
}

Here you could notice that I have replaced the type of the button from submit to button because this button is not contained within a form to submit. I have also gotten rid of the <p> element you were having with id="myForm" which was not only useless but you were ending up with duplicate ids in your DOM which is invalid markup. I have also used the data-url HTML5 attribute on the container div to indicate the url of the server side script that will load the form. And the last thing I did in this file was to override the scripts section we defined earlier in the Layout with a custom script.

So the next part is the custom script: ~/areas/admin/scripts/myscript.js:

$('#BTN').click(function () {
    var $formContainer = $('#formContainer');
    var url = $formContainer.attr('data-url');
    $formContainer.load(url, function () {
        var $form = $('#myForm');
        $.validator.unobtrusive.parse($form);
        $form.submit(function () {
            var $form = $(this);
            if ($form.valid()) {
                $.post(this.action, $(this).serialize(), function (data) {
                    $form.html(data);
                    $form.removeData('validator');
                    $form.removeData('unobtrusiveValidation');
                    $.validator.unobtrusive.parse($form);
                });
            }
            return false;
        });
    });
    return false;
});

Pretty standard code here. We subscribe to the click event of the button and load the partial using an AJAX call. As soon as this is done we instruct the unobtrusive validation framework to parse the newly added contents to our DOM. The next step is to AJAXify the form by subscribing to the .submit event. And because in the success handler we are once again replacing the contents of the container we need to instruct the unobtrusive validation framework to parse the new contents.

and finally the partial:

@model _1.Areas.Admin.Models.AdminModule

@using (Html.BeginForm("Index_partialPost", "Admin", FormMethod.Post, new { id = "myForm" }))
{
    @Html.LabelFor(i => i.MyName)
    @Html.TextBoxFor(i => i.MyName)
    @Html.ValidationMessageFor(i => i.MyName)
    <p id="getDateTimeString"></p>
    <input type="submit" value="Click here" />
}

Here you could notice that I have gotten rid of absolutely any traces of javascript. javascript belongs to separate files. It has nothing to do in views. You should not mix markup and scripts. When you have separate scripts not only that your dynamic markup will be much smaller but also you could take advantage of things like browser caching for the external scripts, minification, ... Another thing you will notice in this partial is that I remove the <script> nodes in which you were referencing jQuery and the jQuery.validate scripts. You already did that in the Layout, do not repeat it twice.