asp.net-coreasp.net-core-3.0

Modal Pop-Up Displaying Incorrectly When ModelState.IsValid = false Redirect


I'm having an issue with my Modal Pop-Up displaying incorrectly when it fails model validation on HttpPost. When the Modal returns data and it fails validation, I want the screen to return to having the modal popup display as a pop-up over the screen that generated the pop-up initially. What is happing is that the pop-up fills the entire screen, without ANY formatting (i.e. it is not a modal popup at this point). It does show the validation messages though, just as unformatted text. Here are all of the pieces of code that I use:

This is in my site.js

(function () {
// Initialize numeric spinner input boxes
//$(".numeric-spinner").spinedit();
// Initialize modal dialog
// attach modal-container bootstrap attributes to links with .modal-link class.
// when a link is clicked with these attributes, bootstrap will display the href content in a modal dialog.
    $('body').on('click', '.modal-link', function (e) {
        e.preventDefault();
        $(this).attr('data-target', '#modal-container');
        $(this).attr('data-toggle', 'modal');
    });
    // Attach listener to .modal-close-btn's so that when the button is pressed the modal dialog disappears
    $('body').on('click', '.modal-close-btn', function () {
        $('#modal-container').modal('hide');
    });
    //clear modal cache, so that new content can be loaded
    $('#modal-container').on('hidden.bs.modal', function () {
        $(this).removeData('bs.modal');
    });
    $('#CancelModal').on('click', function () {
        return false;
    });  
});

This is how I call the pop-up:

<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
     <div class="modal-content"></div>
</div>

<a href="@Url.Action("CreateEdit", new { controller = "Issue", issueid = Model.IssueData.issueId, addedit = "add" })" class="modal-link btn btn-success">Add New Status</a>

This is the controller that handles the HttpPost from the Modal PopUp

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult CreateEdit(StatusViewModel model)
{
    if (ModelState.IsValid)
    {
        //Do Stuff
        return RedirectToAction("edit");

    } else
    {
        return PartialView("_CreateEdit", model);
    }           
}

And here is the Modal-PopUp:

@model MYAPP.ViewModels.StatusViewModel
<!--Modal Body Start-->

<div class="modal-content">
    <!--Modal Header Start-->
    <div class="modal-header">
        <h4 class="modal-title">@ViewBag.Title</h4>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <!--Modal Header End-->
    <form asp-action="CreateEdit" asp-controller="Issue" method="post" enctype="multipart/form-data">
        @Html.AntiForgeryToken()

        <div class="modal-body form-horizontal">
            <div class="form-group row">
                @Html.HiddenFor(model => model.addedit)
                @Html.HiddenFor(model => model.IssueID)
                @Html.HiddenFor(model => model.StatusDate)
                @Html.LabelFor(model => model.Status, new { @class = "col-sm-2 col-form-label" })
                <div class="col-sm-10">
                    <textarea asp-for="@Model.Status" class="form-control" rows="10" placeholder="Enter/Update Status">@Model.Status</textarea>

                </div>
            </div>
            <div class="form-group row">
                @Html.LabelFor(model => model.NextStep, new { @class = "col-sm-2 col-form-label" })
                <div class="col-sm-10">
                    <textarea asp-for="@Model.NextStep" class="form-control" rows="10" placeholder="Please enter the next steps here">@Model.NextStep</textarea>
                </div>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ColorCode" class="control-label"></label>
                @Html.DropDownListFor(modelItem => modelItem.ColorCode, new[] {
               new SelectListItem { Text = " ", Value = "" },
               new SelectListItem { Text = "Red", Value = "R" },
               new SelectListItem { Text = "Yellow", Value = "Y" },
               new SelectListItem { Text = "Green", Value = "G" } })

                <span asp-validation-for="@Model.ColorCode" class="text-danger"></span>
            </div>
            <div>
                <table class="statustable">
                    <tr class="statustablerow">
                        <th></th>
                        <th>Previous Status</th>
                        <th>Previous Next Steps</th>
                    </tr>
                    <tr class="statustabledata">
                        @if (@ViewBag.LastColorCode == "R")
                        {
                            <td rowspan="2" width="2%" style=" background-color:red"></td>
                        }
                        else if (@ViewBag.LastColorCode == "Y")
                        {
                            <td rowspan="2" width="2%" style="background-color: yellow"></td>
                        }
                        else if (@ViewBag.LastColorCode == "G")
                        {
                            <td rowspan="2" width="2%" style="background-color: green"></td>
                        }
                        else
                        {
                            <td rowspan="2" width="2%" style="background-color: gray"></td>
                        }
                        <td width="20%">Previous Status:</td>
                        <td width="78%">@ViewBag.LastStatus</td>
                    </tr>
                    <tr class="statustabledata">
                         <td>Previous Next Steps:</td>
                        <td>@ViewBag.LastNextSteps</td>
                    </tr>

                </table>
            </div>
        <!--Modal Footer Start-->
        <div class="modal-footer">
            <button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Cancel</button>
            <button class="btn btn-success relative" id="btnSubmit" data-save="modal">
                <i class="loader"></i>
                Submit
            </button>
        </div>
        <div class="row">
            &nbsp;
        </div>
 
        <!--Modal Footer End-->
    </form>

</div>
<script type="text/javascript">
    $(function () {
    });
</script>

<!--Modal Body End-->  

How can I get the screen to revert to showing the page with the popup when validation fails?


Solution

  • You should submit the form via ajax and replace the modal with the returned data(html of the partialview), otherwise it will directly return the partialview as a new view.

    I made some changes to your codes and you can refer to the below example:

    Model:

    public class StatusViewModel
    {
        public string addedit { get; set; }
        public int IssueID { get; set; }
        public DateTime StatusDate { get; set; }
        [Required]
        public string Status { get; set; }
        [Required]
        public string NextStep { get; set; }
        [Required]
        public string ColorCode { get; set; }
    }
    

    Edit.cshtml:

    <div id="modal-container" class="modal fade" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
            </div>
        </div>
    </div>
    <a href="@Url.Action("CreateEdit", new { controller = "Issue", issueid = "1", addedit = "add" })" class="modal-link btn btn-success">Add New Status</a>
    
    
    @section scripts{
        <script>
            $('body').on('click', '.modal-link', function () {
                var actionUrl = $(this).attr('href');
                $.get(actionUrl).done(function (data) {
                    $('body').find('.modal-content').html(data);
                });
                $(this).attr('data-target', '#modal-container');
                $(this).attr('data-toggle', 'modal');
            });
    
            $('body').on('click', '.relative', function (e) {
                e.preventDefault();
                var form = $(this).parents('.modal').find('form');
                var actionUrl = form.attr('action');
                var dataToSend = form.serialize();
                $.post(actionUrl, dataToSend).done(function (data) {
                    $('body').find('.modal-content').html(data);
                });
            })
    
            $('body').on('click', '.close', function () {
                $('body').find('#modal-container').modal('hide');
            });
    
            $('#CancelModal').on('click', function () {
                return false;
            });
        </script>
    }
    

    _CreateEdit.cshtml:

    @model StatusViewModel
    <!--Modal Body Start-->
    @{ 
        ViewBag.Title = "Edit";
    }
    
    <div class="modal-header">
        <h4 class="modal-title">@ViewBag.Title</h4>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
        </button>
    </div>
    
    <div class="modal-body form-horizontal">
        <form asp-action="CreateEdit" asp-controller="Issue" method="post" enctype="multipart/form-data">
            @Html.AntiForgeryToken()
            <div class="form-group row">
                @Html.HiddenFor(model => model.addedit)
                @Html.HiddenFor(model => model.IssueID)
                @Html.HiddenFor(model => model.StatusDate)
                @Html.LabelFor(model => model.Status, new { @class = "col-sm-2 col-form-label" })
                <div class="col-sm-10">
                    <textarea asp-for="@Model.Status" class="form-control" rows="10" placeholder="Enter/Update Status">@Model.Status</textarea>
                    <span asp-validation-for="@Model.Status" class="text-danger"></span>
                </div>
            </div>
            <div class="form-group row">
                @Html.LabelFor(model => model.NextStep, new { @class = "col-sm-2 col-form-label" })
                <div class="col-sm-10">
                    <textarea asp-for="@Model.NextStep" class="form-control" rows="10" placeholder="Please enter the next steps here">@Model.NextStep</textarea>
                    <span asp-validation-for="@Model.NextStep" class="text-danger"></span>
                </div>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ColorCode" class="control-label"></label>
                @Html.DropDownListFor(modelItem => modelItem.ColorCode, new[] {
                new SelectListItem { Text = " ", Value = "" },
                new SelectListItem { Text = "Red", Value = "R" },
                new SelectListItem { Text = "Yellow", Value = "Y" },
                new SelectListItem { Text = "Green", Value = "G" } })
    
                <span asp-validation-for="@Model.ColorCode" class="text-danger"></span>
            </div>
            <div>
                <table class="statustable">
                    <tr class="statustablerow">
                        <th></th>
                        <th>Previous Status</th>
                        <th>Previous Next Steps</th>
                    </tr>
                    <tr class="statustabledata">
                        @if (@ViewBag.LastColorCode == "R")
                        {
                            <td rowspan="2" width="2%" style=" background-color:red"></td>
                        }
                        else if (@ViewBag.LastColorCode == "Y")
                        {
                            <td rowspan="2" width="2%" style="background-color: yellow"></td>
                        }
                        else if (@ViewBag.LastColorCode == "G")
                        {
                            <td rowspan="2" width="2%" style="background-color: green"></td>
                        }
                        else
                        {
                            <td rowspan="2" width="2%" style="background-color: gray"></td>
                        }
                        <td width="20%">Previous Status:</td>
                        <td width="78%">@ViewBag.LastStatus</td>
                    </tr>
                    <tr class="statustabledata">
                        <td>Previous Next Steps:</td>
                        <td>@ViewBag.LastNextSteps</td>
                    </tr>
    
                </table>
            </div>
            <!--Modal Footer Start-->
            <div class="modal-footer">
                <button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Cancel</button>
                <input type="submit" class="btn btn-success relative" id="btnSubmit" data-save="modal" value="Submit">
            </div>
            <div class="row">
                &nbsp;
            </div>
        </form>
    </div>
    

    Controller:

    public IActionResult Edit()
    {
        return View();
    }
    
    [HttpGet]
    public ActionResult CreateEdit(int issueid, string addedit)
    {
        var model = new StatusViewModel
        {
            Status = "AAAAA",
            NextStep = "BBBBB"
        };
            
        ViewBag.LastColorCode = "R";
        ViewBag.LastStatus = "CCCC";
        ViewBag.LastNextSteps = "DDDD";
    
        return PartialView("_CreateEdit", model);
            
    }
    
    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult CreateEdit(StatusViewModel model)
    {
        if (ModelState.IsValid)
        {
            //Do Stuff
            return RedirectToAction("edit");
    
        }
        else
        {
            return PartialView("_CreateEdit", model);
        }
    }
    

    Result:

    enter image description here