问题描述
我在 kendo 窗口中使用不显眼的 ajax 来更新表单,一旦它被填写。表单应该动态更新 DOM 元素的 Id,并显示表单内的相关数据,作为从控制器返回。
让我们开始吧,这里是包含部分视图的窗口元素,它是一个表单:
@model Requirement
@{
int localId = Model.Id;
}
<div class="window-content">
<form method="post" data-ajax-url="/Home/Process_Requirement" data-ajax="true" data-ajax-method="post" data-ajax-loading="#spinner" data-ajax-update="#update-form-requirement" data-ajax-success="form_requirement_success">
<div id="update-form-requirement">
<partial name="_Form_Requirement" />
</div><!--/update-panel-->
<div class="window-footer">
<div class="container">
<div class="row no-gutters">
<div class="col">
<button type="submit" class="input-submit float-right">Save</button>
</div>
</div>
</div>
</div>
</form>
</div>
_Form_Requirement
@model Requirement
@{
int localId = Model.Id;
}
<div class="tab-content">
<div class="tab-pane fade show active" id="form-requirement-basic-@localId" role="tabpanel" aria-labelledby="requirement-tab">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="text" id="Id_@localId" name="Id" asp-for="Id" readonly />
<input type="text" id="CreatedUser_@localId" asp-for="CreatedUser" readonly />
<div class="container">
<div class="row">
<div class="col">
<div class="form-group">
<label>Vessel Type</label>
<kendo-dropdownlist name="VesselType"
for="VesselType"
id="VesselType_@localId"
datatextfield="TypeName"
datavaluefield="Id"
min-length="3"
style="width: 100%"
value-primitive="true"
option-label="Select vessel type"
footer-template="<button class='dropdown-button k-icon k-i-plus-outline' data-object-title='Add vessel type' data-object-function='_Window_Vessel_Type' onclick='open_data_window(this,event)'></button>"
filter="FilterType.Contains">
<datasource type="DataSourceTagHelperType.Ajax" page-size="80">
<transport>
<read url="/Vessel/ReadVesselTypes" />
</transport>
</datasource>
<popup-animation>
<open duration="300" effects="fadeIn" />
<close duration="300" effects="fadeOut" />
</popup-animation>
</kendo-dropdownlist>
</div>
</div>
</div>
</div>
</div>
</div>
提交表单时,控制器操作会执行以下操作:
/Home/Process_Requirement
public IActionResult Process_Requirement(Requirement model)
{
//Define the partial view we want
string modal = "_Form_Requirement";
//If the Id is 0 then create a new requirement
if (model.Id == 0)
{
if (ModelState.IsValid)
{
try {
_requirementService.InsertRequirement(model);
var getData = _requirementService.GetRequirement(model.Id);
return PartialView(modal,getData);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
else
{
try
{
_requirementService.UpdateRequirement(model);
return PartialView(modal,model);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return PartialView(modal);
}
因此,当您第一次打开一个窗口来创建新需求时,localId
为 0
,因为您没有编辑一个,这是预期的行为。
然后当您填写所有详细信息并提交表单时,数据会发布到数据库并正确保存,但模型似乎没有使用新数据更新,例如 Id 的输入保持为 0 :
<input type="text" id="Id_@localId" name="Id" asp-for="Id" readonly />
但输入的 id 更新为新创建的 id 号。为什么会发生这种情况,我能做些什么吗?
解决方法
你有一个错误。修复最后一次返回
return PartialView(modal,model);
,
Id 是主键吗?如果是这样,不建议更改主键,您应该添加一个新列作为键。
数据已发布到数据库并正确保存,但模型似乎没有使用新数据更新
这可能是由并发问题引起的。我现在看不到你的更新代码,但你可以
尝试像这样更改您的更新代码:
public async Task<IActionResult> Process_Requirement(Requirement model)
{
string modal = "_Form_Requirement";
if (model.Id == 0)
{
//....
}
else //to update
{
await TryUpdateModelAsync<Requirement>(_context.Requirements.FirstOrDefault(x => x.RId ==model.RId),"",c => c.Id,c => c.CreatedUser);
_context.SaveChanges();
return PartialView(modal,model);
}
return PartialView(modal);
}
我的模型:
public class Requirement
{
[Key]
public int RId { get; set; } //new column
public int Id { get; set; }
public string CreatedUser { get; set; }
}
部分地,传递带有隐藏字段的密钥:
<input type="text" asp-for="RId" hidden/>
<input type="text" id="Id_@localId" name="Id" asp-for="Id" />
<input type="text" id="CreatedUser_@localId" asp-for="CreatedUser" />
结果: