EditorTemplate asp-for="Property" 与 value="@Model.Property"
EditorTemplate asp-for="Property" vs value="@Model.Property"
我正在使用 .NET Core 3.0 构建一个 Web 应用程序,其中包含一个用于值列表的 EditorTemplate。此 EditorTemplate 位于 PartialView 内。每当我从列表中添加或删除记录时,我的 ActionMethod 都会返回一个 PartialView。
令人困惑的是,每当我从列表的 top/middle 中删除一条记录时,EditorTemplate 就会乱七八糟。请检查下面的图片。
问题一:为什么会这样,如何解决?
问题2:为什么我用<input type="text" asp-for="FilterId" class="form-control" />
和<input type="text" value="@Model.FilterId" />
时值不一样
删除前
删除后
AdvancedFilterVM EditorTemplate
@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> </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);
}
我可以重现同样的问题。我以为是缓存引起的。但事实并非如此。真是刷新了我的认知:EditorFor
renders the template using ModelState prior to Model.
快速修复:
在渲染之前清除 ModelState:
ModelState.Clear();
return PartialView("_SurveyFilter", surveySubmissionVM);
更多技术信息:
引自MSDN Blog:
ASP.NET MVC assumes ... Therefore, the Html Helpers actually check in ModelState for the value to display in a field before they look in the Model. This enables them to redisplay erroneous data that was entered by the user, and a matching error message if needed.
网上也有一些话题在讨论这种行为:
- https://forums.asp.net/t/1527149.aspx?A+Bug+EditorFor+and+DisplayFor+don+t+display+same+value+EditorFor+out+of+date
- How does Html.EditorFor process changes to the model
- https://blogs.msdn.microsoft.com/simonince/2010/05/05/asp-net-mvcs-html-helpers-render-the-wrong-value/
- https://exceptionnotfound.net/modelstate-values-override-model-values-in-htmlhelpers/
(尽管它们都是关于 ASP.NET,该理论也适用于 ASP.NET Core)
我正在使用 .NET Core 3.0 构建一个 Web 应用程序,其中包含一个用于值列表的 EditorTemplate。此 EditorTemplate 位于 PartialView 内。每当我从列表中添加或删除记录时,我的 ActionMethod 都会返回一个 PartialView。
令人困惑的是,每当我从列表的 top/middle 中删除一条记录时,EditorTemplate 就会乱七八糟。请检查下面的图片。
问题一:为什么会这样,如何解决?
问题2:为什么我用<input type="text" asp-for="FilterId" class="form-control" />
和<input type="text" value="@Model.FilterId" />
删除前
删除后
AdvancedFilterVM EditorTemplate
@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> </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);
}
我可以重现同样的问题。我以为是缓存引起的。但事实并非如此。真是刷新了我的认知:EditorFor
renders the template using ModelState prior to Model.
快速修复:
在渲染之前清除 ModelState:
ModelState.Clear();
return PartialView("_SurveyFilter", surveySubmissionVM);
更多技术信息:
引自MSDN Blog:
ASP.NET MVC assumes ... Therefore, the Html Helpers actually check in ModelState for the value to display in a field before they look in the Model. This enables them to redisplay erroneous data that was entered by the user, and a matching error message if needed.
网上也有一些话题在讨论这种行为:
- https://forums.asp.net/t/1527149.aspx?A+Bug+EditorFor+and+DisplayFor+don+t+display+same+value+EditorFor+out+of+date
- How does Html.EditorFor process changes to the model
- https://blogs.msdn.microsoft.com/simonince/2010/05/05/asp-net-mvcs-html-helpers-render-the-wrong-value/
- https://exceptionnotfound.net/modelstate-values-override-model-values-in-htmlhelpers/
(尽管它们都是关于 ASP.NET,该理论也适用于 ASP.NET Core)