问题的答案:
- 您不应该将 responseId 传递给部分,您应该从响应对象传递备忘录集合,并使您的部分视图强类型化到该集合。
- 请参阅下面的完整代码示例。
- 您不需要部分表单,因为您正在进行简单的 ajax 调用来添加新备忘录。请参阅下面的完整代码示例。
这是我目前正在从事的一个项目的修改示例:
有一些代码要遵循,所以这里是:
这是我的模型。职业规划表上有几个部分,其中一个是选择和更新能力的部分。SelectCompetencies 模型中包含一系列能力。用户将能够添加能力。当他们这样做时,它将被添加到数据库中,并将更新部分中的能力列表。
public class CareerPlanningFormViewModel
{
// code removed ...
public SelectCompetenciesModel SelectCompetencies { get; set; }
// code removed ...
}
public class SelectCompetenciesModel
{
public int CareerPlanningFormID { get; set; }
public IList<CompetencyModel> Competencies { get; set; }
public byte MaximumCompetenciesAllowed { get; set; }
}
public class CompetencyModel
{
public int CompetencyID { get; set; }
public int? CompetencyOptionID { get; set; }
public string ActionPlan { get; set; }
public IDictionary<int, string> CompetencyOptions { get; set; }
}
职业规划表主视图:/Views/CPF/CareerPlanningForm.cshtml
@model MyNamespace.Models.CareerPlanningForm.CareerPlanningFormViewModel
<link rel="stylesheet" href="@Url.Content("~/Content/CreateCPF.css")" />
@using (Html.BeginForm())
{
// other sections loaded here...
// code removed for brevity...
@Html.Partial("SelectCompetencies", Model.SelectCompetencies)
// other sections loaded here...
// code removed for brevity...
}
SelectCompetencies 部分:/Views/CPF/SelectCompetencies.cshtml 用户将填写新的行动计划文本并单击添加能力按钮。这将通过 ajax 发布到 CPFController/NewCompetencyTemplate
@model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesModel
@Html.HiddenFor(m => m.CareerPlanningFormID)
<h3>Select Competencies</h3>
<p class="guidance">
Select up to @Model.MaximumCompetenciesAllowed competencies to focus on improving.
</p>
<table id="CompetenciesTable">
<thead>
<tr>
<th>Competency</th>
<th>Action Plan:</th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.Competencies.Count(); i++)
{
@Html.EditorFor(m => m.Competencies[i])
}
</tbody>
<tfoot id="CompetenciesTableFooter" class="@(Model.Competencies.Count() < Model.MaximumCompetenciesAllowed ? "" : "hidden")">
<tr>
<td colspan="2">
@Html.TextArea("NewActionPlanText")
@Html.Button(ButtonType.Button, "Add Another Competency", "add", new { id = "AddCompetencyButton" })
</td>
</tr>
</tfoot>
</table>
@section script
{
<script>
jQuery(document).ready(function ($) {
var competenciesTableBody = $('#CompetenciesTable tbody'),
competenciesTableFooter = $('#CompetenciesTableFooter'),
addCompetencyButton = $('#AddCompetencyButton'),
newCompetencyTemplateUrl = '@Url.Content("~/CPF/NewCompetencyTemplate")',
count = competenciesTableBody.find('tr').length,
newActionPlanText = $('#NewActionPlanText'),
careerPlanningFormID = $('#CareerPlanningFormID');
addCompetencyButton.click(function () {
$.ajax({
url: newCompetencyTemplateUrl(),
type: 'POST',
data: {
careerPlanningFormID: careerPlanningFormID,
actionPlan: newActionPlanText,
itemCount: count
},
dataType: 'html',
success: function (data) {
var elements = $(data);
// other code removed here...
competenciesTableBody.append(elements);
// other code removed here...
}
});
});
});
</script>
}
视图/CPF/EditorTemplates/CompetencyModel.cshtml
@model MyNamespace.Models.CareerPlanningForm.CompetencyModel
<tr class="competency">
<td>
@Html.DropDownListFor(m => m.CompetencyOptionID, new SelectList(Model.CompetencyOptions, "Key", "Value"), "Select competency...")
</td>
<td>
@Html.TextAreaFor(m => m.ActionPlan, new { @class = "competencyActionPlan" })
@Html.HiddenFor(m => m.CompetencyID)
</td>
</tr>
包含添加新能力的操作的控制器:/Controllers/CPFController.cs
这将调用 CareerPlanningFormService 来添加新的能力,并将返回 NewCompetencyTemplate 的部分视图,该视图将呈现新的能力
public class CPFController : Controller
{
private readonly ICareerPlanningFormService careerPlanningFormService;
public CPFController(ICareerPlanningFormService careerPlanningFormService)
{
this.careerPlanningFormService = careerPlanningFormService;
}
[HttpPost]
public PartialViewResult NewCompetencyTemplate(int careerPlanningFormID, int itemCount, string newActionPlanText)
{
var count = itemCount + 1;
// Even though we're only rendering a single item template, we use a list
// to trick MVC into generating fields with correctly indexed name attributes
// i.e. Competencies[1].ActionPlan
var model = new SelectCompetenciesModel
{
Competencies = Enumerable.Repeat<CompetencyModel>(null, count).ToList()
};
model.Competencies[count - 1] = this.careerPlanningFormService.BuildNewCompetencyModel(careerPlanningFormID, newActionPlanText);
return this.PartialView(model);
}
}
我的服务类:CareerPlanningFormService.cs
这处理业务逻辑并调用存储库以将项目添加到数据库并返回新的 CompetencyModel
public class CareerPlanningFormService : ICareerPlanningFormService
{
private readonly IMyRenamedRepository repository;
private readonly IPrincipal currentUser;
public CareerPlanningFormService(
IMyRenamedRepository repository,
IPrincipal currentUser)
{
this.repository = repository;
this.currentUser = currentUser;
}
public CompetencyModel BuildNewCompetencyModel(int careerPlanningFormID, string newActionPlanText)
{
var competency = new Competency
{
CareerPlanningFormID = careerPlanningFormID,
CompetencyOptionID = null,
ActionPlan = newActionPlanText
};
this.repository.Add(competency);
this.repository.Commit();
return new CompetencyModel
{
CompetencyID = competency.CompetencyID,
CompetencyOptionID = competency.CompetencyOptionID,
ActionPlan = competency.ActionPlan,
CompetencyOptions = this.GetCompetencyOptionsForCareerPlanningFormID(careerPlanningFormID)
};
}
}
现在,NewCompetencyTemplate 的部分内容:Views/CPF/NewCompetencyTemplate.cshtml
这很简单,它只是呈现与上面相同的编辑器模板,用于集合中的最后一个能力(我们刚刚添加)
@model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesViewModel
@Html.EditorFor(m => m.Competencies[Model.Competencies.Count() - 1])
当 ajax 调用成功时,它会从它调用的控制器操作方法接收到这个部分返回。然后它获取部分并将其附加到能力表主体
// snippet from ajax call above
competenciesTableBody.append(elements);
我希望这有帮助。如果您有任何其他问题,请告诉我。