更新主窗体以在返回 PartialViewResult 时显示自定义验证消息

Update Main Form to display Custom validation message when returning PartialViewResult

我有一个主视图,这个主视图有一个 div 标签,在 Ajax 调用控制器后将包含部分视图。

这是负责发起 ajax 调用的分部视图:

@model EDR.Presentation.WebMain.ViewModels.MvcPatientDetailsHIVViewModel

<div class="form-group-sm">
    @Html.LabelFor(m => m.HIVTestTestDate, new { @class = "control-label" })
    @Html.EditorFor(m => m.HIVTestTestDate, new { htmlAttributes = new { @class = "form-control form-control-custom-50" } })
</div>

<div class="form-group-sm">
    @Html.LabelFor(m => m.HIVTestTestResult, new { @class = "control-label" })
    @Html.DropDownListFor(m => m.HIVTestTestResult, Model.SelectList_HIVTestedResult, new { @class = "form-control form-control-custom-50" })
</div>

<div class="form-group-sm">
    @Html.LabelFor(m => m.HIVTestCD4Count, new { @class = "control-label" })
    @Html.EditorFor(m => m.HIVTestCD4Count, new { htmlAttributes = new { @class = "form-control form-control-custom-50" } })
</div>

<input type="button" value="Add" id="btnAddNewTest" class="btn btn-info" />
<input type="button" value="Cancel" id="btnCancelAdd" class="btn btn-danger" />

这是我的 ajax 电话:

$('#btnAddNewTest').on("click", function () {
        var date = $('#HIVTestTestDate').val();
        var result = $('#HIVTestTestResult').val();
        var cd4 = $('#HIVTestCD4Count').val();
        var pID = $('#PatientID').val();

        var dataToSend = { patientID: pID, testDate: date, resultID: result, cd4Count: cd4 };

        $.ajax({
            url: '/HIVInformation/AddHIVTest/',
            type: 'post',
            data: dataToSend,
            success: function (partialViewReceived) {
                $('#HIVTestCollection').html(partialViewReceived);
            }
        });
    });

这是控制器中被 ajax 调用调用的操作:

public PartialViewResult AddHIVTest(Guid patientID, DateTime testDate, Guid resultID, int cd4Count)
        {
            MvcPatientDetailsHIVViewModel model = new MvcPatientDetailsHIVViewModel(patientID);
            model.LoadAllData();

            try
            {
                //add the HIV Test
                model.HIVTestResult = new Common.Models.PatientHIVTestModel()
                {
                    ID = Guid.NewGuid(),
                    PatientID = patientID,
                    TestDate = testDate,
                    HIVTestResultID = resultID,
                    CD4Count = cd4Count
                };

                //call the add method
                model.AddHIVTestResults();
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", ex);
            }

            return PartialView("_HIVTestCollection", model);
        }

这是在 successfully/unsuccessfully 尝试添加新的 HIV 测试后加载的部分视图。

@model EDR.Presentation.WebMain.ViewModels.MvcPatientDetailsHIVViewModel
@using EDR.Presentation.WebMain.Helpers

@if (Model.PatientHIVTestCollection != null && Model.PatientHIVTestCollection.Count > 0)
{
    <div class="table-responsive">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th>Date</th>
                    <th>Test Result</th>
                    <th>CD4 Count</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var hivTest in Model.PatientHIVTestCollection.OrderByDescending((x) => x.TestDate))
                {
                    <tr>
                        <td>@RazorHelper.ToDateString(() => hivTest.TestDate)</td>
                        <td>@RazorHelper.ToString(() => hivTest.HIVTestResult.DisplayName)</td>
                        <td>@RazorHelper.ToString(() => hivTest.CD4Count)</td>
                        <td>
                            @Ajax.ActionLink("Edit", "EditHIVTest", new { patientID = Model.PatientID, testID = hivTest.ID }, new AjaxOptions() { HttpMethod = "get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "testEdit" }, new { @class = "btn btn-info" })
                            @Ajax.ActionLink("Delete", "DeleteHIVTest", new { patientID = Model.PatientID, testID = hivTest.ID }, new AjaxOptions() { HttpMethod = "get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "HIVTestCollection" }, new { @class = "btn btn-danger" })
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
}
else
{
    <text>No Data to display</text>
}

我在捕获到异常后进行了验证,验证消息已添加到 ModelState。

我知道这个分部视图是动态添加到主视图的,但是我怎样才能重置主视图以显示添加到 ModelState 的验证消息。我不想在局部视图中显示验证消息。

这是一个部分视图,它也出现在主视图上,用于显示验证消息。

@model ModelStateDictionary

@if (!Model.IsValid)
{
    <div class="panel panel-danger">
        <div class="panel-heading">Validation Errors</div>
        <div class="panel-body">
            <ul>
                @foreach (var modelError in
                             Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
                {
                    <li>@modelError.ErrorMessage</li>
                }
            </ul>
        </div>
    </div>
}

如有任何帮助,我们将不胜感激。

在您的 AddHIVTest() 控制器方法中,添加 ModelState 错误毫无意义。这些设计用于与表单关联的 ValidationSummary()ValidationMessageFor() 助手,但关联的部分没有表单。相反,您可以将错误消息添加到视图模型或 ViewBag 属性,例如

catch (Exception ex)
{
  ViewBag.ErrorMessage = ex.ToString();
}

然后您可以在 _HIVTestCollection 部分中将其渲染为(比如)

<div id="errormessage">@ViewBag.ErrorMessage</div>

然后,如果您想在主视图中的其他位置显示该消息,而不是在呈现局部视图的位置,请修改 ajax 函数以将 <div> 移动到新位置。假设主视图包含一个元素

<div id="errorcontainer"><div> // placeholder for the error message
.... // other elements
<div id="HIVTestCollection"><div> // placeholder for the partial

然后

$.ajax({
    url: '/HIVInformation/AddHIVTest/',
    type: 'post',
    data: dataToSend,
    success: function (partialViewReceived) {
        $('#HIVTestCollection').html(partialViewReceived);
        $('#errorcontainer').append($('#errormessage')); // move the message from the partial to the placeholder in the main view
    }
});

另一种选择是使用 this answer 中描述的技术生成 2 个部分视图(一个有错误)并 return 它们作为字符串(在 JsonResult 中)。 =23=]