Я работаю над веб-сайтом запроса проекта и создаю фрагмент, в котором сотрудники, работающие над проектом, могут добавлять оценки за количество времени, которое потребуется для завершения области проекта. Я хотел, чтобы эта страница отправила произвольное количество оценок обратно в действие «Редактировать», но я здесь что-то пропустил.Сильно типизированный вид не инициализируется?
В моем представлении я использую Html.BeginCollectionItem
от here помощника, чтобы помочь с материалом AJAX-y в Html.RenderPartial("_WorkEstimateEditorRow", item);
.
Edit: я борюсь с частями AJAX этого прямо сейчас - я вижу, что значения возвращаются в Request.Form
и свойствах совпадают с моим WorkEstimate
класса правильно, но даже когда я изменить действие контроллера чтобы просто принять оценки IEnumerable<WorkEstimate>
, она равна нулю.
Это выходное значение из одной строки, используя Html.BeginCollectionItem
:
<input data-val="true" data-val-number="The field EstimateId must be a number." data-val-required="The EstimateId field is required." id="estimates_d32afd89-987e-4d09-a847-abfc33dde220__EstimateId" name="estimates[d32afd89-987e-4d09-a847-abfc33dde220].EstimateId" value="0" type="hidden">
<input id="estimates_d32afd89-987e-4d09-a847-abfc33dde220__Estimator" name="estimates[d32afd89-987e-4d09-a847-abfc33dde220].Estimator" value="" type="hidden">
<span class="editor-label">
<label for="estimates_d32afd89-987e-4d09-a847-abfc33dde220__WorkArea">Work Area</label>
</span>
<span class="editor-field">
<input class="text-box single-line" id="estimates_d32afd89-987e-4d09-a847-abfc33dde220__WorkArea" name="estimates[d32afd89-987e-4d09-a847-abfc33dde220].WorkArea" value="" type="text">
<span class="field-validation-valid" data-valmsg-for="estimates[d32afd89-987e-4d09-a847-abfc33dde220].WorkArea" data-valmsg-replace="true"></span>
</span>
<span class="editor-label">
<label for="estimates_d32afd89-987e-4d09-a847-abfc33dde220__Hours">Hours</label>
</span>
<span class="editor-field">
<input class="text-box single-line" data-val="true" data-val-number="The field Hours must be a number." data-val-required="The Hours field is required." id="estimates_d32afd89-987e-4d09-a847-abfc33dde220__Hours" name="estimates[d32afd89-987e-4d09-a847-abfc33dde220].Hours" value="0" type="number">
<span class="field-validation-valid" data-valmsg-for="estimates[d32afd89-987e-4d09-a847-abfc33dde220].Hours" data-valmsg-replace="true"></span>
</span>
<a href="#" class="deleteRow">[x]</a>
<hr>
name
атрибут является то, что попадается в Request.Form
на пост действий. Я также попытался изменить действие своего контроллера, поэтому он получает IEnumerable<WorkEstimate>
без каких-либо изменений.
Модель
public class EstimationManager
{
public EstimationManager()
{
CurrentUser = new WebUser();
Project = null;
EstimationData = new WorkEstimateRepository();
Estimates = new List<WorkEstimate>();
}
public EstimationManager(ApprovedProject project, WebUser currentUser)
: this(project, currentUser, new WorkEstimateRepository())
{ }
public EstimationManager(ApprovedProject project, WebUser currentUser, IWorkEstimateRepository repository)
{
Project = project;
CurrentUser = currentUser;
EstimationData = repository;
Estimates = EstimationData.Get(Project);
}
IWorkEstimateRepository EstimationData { get; set; }
public WebUser CurrentUser { get; set; }
public ApprovedProject Project { get; set; }
public List<WorkEstimate> Estimates { get; set; }
public bool CurrentUserHasWorkerAccess
{
get
{
return CurrentUser != null
&& CurrentUser.AccessLevels.HasWorkerAccess
&& (Project == null || CurrentUser.AccessLevels.WorkerUnit == Project.CurrentWorkerUnit);
}
}
}
Действие контроллера
public class EstimatesController : BaseSessionController
{
private IProjectRepository _projects;
private IWorkEstimateRepository _estimates;
EstimationManager manager;
public EstimatesController()
: this(new WorkEstimateRepository(), new ProjectRepository())
{ }
public EstimatesController(IWorkEstimateRepository estimates, IProjectRepository projects)
{
_estimates = estimates;
_projects = projects;
}
//
// GET: /Estimates/Edit/5
public ActionResult Edit(int id)
{
ApprovedProject details = _projects.Get(id);
manager = new EstimationManager(details, CurrentUser, _estimates);
return View(manager);
}
//
// POST: /Estimates/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
ApprovedProject details = _projects.Get(id);
manager = new EstimationManager(details, CurrentUser, _estimates);
if (TryUpdateModel(manager)
&& _estimates.TrySave(manager))
{
return RedirectToAction("Details", new { id = id });
}
else
{
foreach (WorkEstimate item in manager.Estimates)
{
foreach (RuleViolation currentViolation in item.GetRuleViolations())
{
ModelState.AddModelError(item.WorkArea + currentViolation.PropertyName, currentViolation.ErrorMessage);
}
}
return View(manager);
}
}
}
Посмотреть
@model ProjectRequests.Web.Models.Project.Estimates.EstimationManager
@{
ViewBag.Title = "Edit Estimate Details for " + Model.Project.Name;
}
<h2>Edit Estimate Details for @Model.Project.Name</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>Estimation Manager</legend>
<span id="editorRows">
@foreach (ProjectRequests.Web.Models.Project.Estimates.WorkEstimate item in Model.Estimates)
{
if (Model.CurrentUser == item.Estimator)
{
Html.RenderPartial("_WorkEstimateEditorRow", item);
}
else
{
Html.DisplayFor(modelItem => item);
}
}
</span>
@if (Model.CurrentUserHasWorkerAccess)
{
@Html.ActionLink("Add another estimate.", "BlankEstimateRow", null, new { id = "addItem" })
<p>
<input type="submit" value="Save" />
</p>
}
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$().ready(function() {
$("#addItem").click(function() {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$("#editorRows").append(html);
}
});
return false;
});
$("#editorRows").on("click", ".deleteRow", function() {
$(this).closest(".editorRow").remove();
return false;
});
});
</script>
}
Когда подпись моей Редактировать действие, я s public ActionResult Edit(int id, FormCollection collection)
, представление возвращает соответствующие данные, но TryUpdateModel
фактически не обновляет свойство Estimates
. И наоборот, public ActionResult Edit(int id, EstimationManager newManager)
не устанавливает Estimates
. Идея вручную просеивать через FormCollection
, чтобы вытащить значения из страницы, сильно пахнет запахом большого кода, и это оставляет мне ощущение, что я должен решать эту проблему по-другому.
Часть 'foreach' действительно даже не выполняется. Я просто обрабатываю раздел AJAX прямо сейчас (что неясно в вопросе). Я попытался использовать 'BindAttribute', как вы предложили, но мне не повезло. Я обновлю вопрос с помощью некоторых из моего HTML-кода. – jwiscarson