首页 > 解决方案 > EditorTemplate asp-for="Property" vs value="@Model.Property"

问题描述

我正在使用 .NET Core 3.0 构建一个 Web 应用程序,其中包含一个用于值列表的 EditorTemplate。此 EditorTemplate 位于 PartialView 内。每当我从列表中添加或删除记录时,我的 ActionMethod 都会返回 PartialView。

令人困惑的是,每当我从列表的顶部/中间删除一条记录时,EditorTemplate 就会搞砸。请检查下面的图片。

问题1:为什么会发生以及如何解决?

问题 2:<input type="text" asp-for="FilterId" class="form-control" />为什么我使用&时值不同<input type="text" value="@Model.FilterId" />

删除前 删除前的编辑器模板

删除后 删除后的EditorTemplate

AdvancedFilterVM 编辑器模板

@model SSAQ.Web.ViewModels.AdvancedFilterVM

<tr>
    <td>
        <input type="text" asp-for="FilterId" class="form-control" />
    </td>
    <td>
        @Html.TextBoxFor(m => m.FilterId, new { @class="form-control" })
    </td>
    <td>
        <input type="text" value="@Model.FilterId" class="form-control" />
    </td>
    <td style="text-align:center;vertical-align:middle;">
        <a href="#" class="deleteFilter" data-filterid="@Model.FilterId"><i style="font-size:20px;" class="fa fa-times"></i></a>
    </td>
</tr>

_SurveyFilter PartialView

@model SSAQ.Web.ViewModels.SurveySubmissionViewModel
@if (Model.AdvancedFilter?.Any() == true)
{
<table class="table" id="tblFilter">
    <thead>
        <tr>
            <th>Using asp-for=FilterId</th>
            <th>Using @@Html.TextBoxFor(m => m.FilterId)</th>
            <th>Using value=@@Model.FilterId</th>
            <th>&nbsp;</th>
        </tr>
    </thead>
    <tbody id="tblFilterSurvey">
        @Html.EditorFor(m => m.AdvancedFilter)
    </tbody>
</table>
}

jQuery删除行

$('body').on('click', '.deleteFilter', function (e) {
    e.preventDefault();
    var filterId = $(this).data('filterid');
    var formData = $("#formFilter").serializeArray();
    formData.push({ name: 'filterId', value: filterId });
    $.ajax({
        type: 'POST',
        context: this,
        url: '@Url.Content("~/Survey/DeleteFilterRow")',
        data: formData,
        success: function (response) {
            $('#filterTableDiv').html(response);
        }
    });
});

DeleteFilterRow 操作方法

public IActionResult DeleteFilterRow(SurveySubmissionViewModel surveySubmissionVM, Guid filterIdToRemove)
{
    surveySubmissionVM.AdvancedFilter.Remove(surveySubmissionVM.AdvancedFilter.Single(m => m.FilterId == filterIdToRemove));
    return PartialView("_SurveyFilter", surveySubmissionVM);
}

标签: asp.net-corepartial-viewsasp.net-core-3.0mvc-editor-templates

解决方案


我可以重现同样的问题。我还以为是缓存造成的。但事实并非如此。它确实刷新了我的知识:EditorFor在 Model 之前使用 ModelState 渲染模板。

快速解决:

渲染前清除 ModelState:

ModelState.Clear();
return PartialView("_SurveyFilter", surveySubmissionVM);

更多技术信息:

引用自MSDN 博客

ASP.NET MVC 假设......因此,Html Helpers 在查看 Model 之前实际上会在 ModelState 中检查要在字段中显示的值。这使他们能够重新显示用户输入的错误数据,并在需要时显示匹配的错误消息。

网上也有一些线程在网上谈论这种行为:

  1. https://forums.asp.net/t/1527149.aspx?A+Bug+EditorFor+and+DisplayFor+don+t+display+same+value+EditorFor+out+of+date
  2. Html.EditorFor 如何处理对模型的更改
  3. https://blogs.msdn.microsoft.com/simonince/2010/05/05/asp-net-mvcs-html-helpers-render-the-wrong-value/
  4. https://exceptionnotfound.net/modelstate-values-override-model-values-in-htmlhelpers/

(虽然它们都是关于 ASP.NET,但该理论也适用于 ASP.NET Core)


推荐阅读