다음 뷰 모델 구조가 있습니다 : BaseViewModel 유형의 속성 모델을 포함하는 ItemViewModel.포스트 ASP.NET MVC에 중첩 된 뷰 모델 바인딩 목록
이 구체적인 예에서 Model은 WeekManagerWorkScheduleViewModel 유형입니다. 이 뷰 모델은 차례로 ManagerWorkScheduleViewModel 유형의 IEnumerable로 구성됩니다. ., 사용되는 다음 ItemView.cshtml 내부
:<form class="form-horizontal" id="@Model.FormName" name="@Model.FormName" onsubmit="@Model.OnSubmitFunction">
<div class="form-group form-group-sm">
@Html.EditorFor(model => model.Model, Model.ItemViewName + "View")
</div>
<button class="btn pull-left" type="submit" style="margin: 2px;">
<span class="glyphicon glyphicon-save"></span>
@Model.ViewConfiguration.SaveText @Model.ItemTitle
</button>
</form>
내가 몇 가지 세부 사항을 생략 한 (기본적으로 CRUD 버튼을 추가할지 여부를 결정하는 것 경우의 무리가 Model.ItemViewName는 유형 이름입니다 (의 이 경우 그 WeekManagerWorkScheduleViewModel)
public class WeekManagerWorkScheduleViewModel : BaseViewModel
{
[HiddenInput]
public int RegionId { get; set; }
[HiddenInput]
public IEnumerable<DateTime> Dates { get; set; }
public IEnumerable<ManagerWorkScheduleViewModel> WorkSchedules { get; set; }
}
가 WeekManagerWorkScheduleView.cshtml은 다음과 같습니다.
@using DRSTransportPortal.ViewModels
@model WeekManagerWorkScheduleViewModel
@{
ViewBag.Title = "Ugentlig arbejdsplan - ledere";
}
@Html.HiddenFor(m => m.RegionId)
<table class="table">
<thead>
<tr>
<th><b>Leder</b></th>
<th><b>Uge</b></th>
<th><b>Mandag</b></th>
<th><b>Tirsdag</b></th>
<th><b>Onsdag</b></th>
<th><b>Torsdag</b></th>
<th><b>Fredag</b></th>
<th><b>Lørdag</b></th>
<th><b>Søndag</b></th>
</tr>
<tr>
<th></th>
<th></th>
@foreach (var date in Model.Dates)
{
<th><i><small>@date.Date.ToString("dd-MM-yyyy")</small></i></th>
}
</tr>
</thead>
<tbody>
@Html.EditorFor(m => m.WorkSchedules)
</tbody>
</table>
,536,913 63,210
내가보기/imalazysod/EditorTemplates (나는 면도기에서 파생 된 사용자 지정보기 엔진을 사용하고 같은 MVC는이 위치를 알고)에 거주 ManagerWorkScheduleViewModel.cshtml라는 전망이 :
@using DRSTransportPortal.ViewModels
@model ManagerWorkScheduleViewModel
<tr id="@Model.Id">
<td>@Html.HiddenFor(m => m.Id)</td>
<td>@Html.DisplayFor(m => m.ManagerName, new { htmlAttributes = new { @class = "form-control editoritem" } })</td>
<td>@Html.DisplayFor(m => m.DateWeekText, new { htmlAttributes = new { @class = "form-control editoritem" } })</td>
<td>@Html.EditorFor(m => m.MondayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.TuesdayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.WednesdayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.ThursdayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.FridayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.SaturdayCodeChoice, new { @class = "form-control editoritem" })</td>
<td>@Html.EditorFor(m => m.SundayCodeChoice, new { @class = "form-control editoritem" })</td>
</tr>
은 "선택"속성을 모두 ChoiceViewModel.cshtml를 사용하여 ChoiceViewModel 유형입니다.
지금, 모든 것이 제대로 렌더링 : Screenshot (names omitted). Red box indicates 1 (one) nested viewmodel
생성 된 HTML은 다음과 같습니다 (첫 번째 행과 처음 몇 세포가 여기에 표시됩니다) :
<tr id="134">
<td><input name="Model.WorkSchedules[0].Id" id="Model_WorkSchedules_0__Id" type="hidden" value="134" data-val-required="Feltet Id skal udfyldes." data-val="true" data-val-number="The field Id must be a number."></td>
<td>OMITTED</td>
<td>2016 - 36</td>
<td>
<select name="Model.WorkSchedules[0].MondayCodeChoice.SelectedValue" class="form-control editoritem dropdown" id="SelectChoices" onchange="">
<option value="1">06:00 - 14:00</option>
<option value="19">06:00 - 18:00</option>
<option value="31">08:00 - 16:00</option>
<option value="2">10:00 - 18:00</option>
<option value="32">10:00 - 18:00</option>
<option value="23">Bagvagt</option>
<option value="22">Ferie</option>
<option value="8">Fri</option>
<option value="3">Kontor</option>
<option value="15">Kussus</option>
<option value="16">Syg</option>
</select>
</td>
REST OF HTML IS OMMITTED (CONTINUES FOR 12 ROWS WITH 10 CELLS EACH)
</tr>
을 그러나, 나는 다시 게시 할 때 (jQuery, ajax btw 사용) 이것은 내가 얻은 것입니다. Controller breakpoint, after modelbinding
BaseViewModel에 사용자 지정 모델 바인더를 넣고 보았지만 n 괜찮아 보입니다. 올바른 유형 (WeekManagerWorkScheduleViewModel 등)을 결정합니다. 이것을 사용하면 ControllerContext -> ...-> Request의 Forms 요소가 다음과 같이됩니다. {Model.Id = 141 & ModelType = DRSTransportPortal.ViewModels.WeekManagerWorkScheduleViewModel % 2c + DRSTransportPortal % 2c + Version % 3d1.0.0.0 % 2c + 문화 % 3dneutral % 2C + PublicKeyToken 3dnull % & & Model.RegionId = 1 % Model.WorkSchedules 5b0 5d.Id % = 134 % & Model.WorkSchedules 5b0 5d.MondayCodeChoice.SelectedValue % = 22 %의 & Model.WorkSchedules 5b0 %의 5D .TuesdayCodeChoice.SelectedValue = 1 & Model.WorkSchedules %의 5b0 5d.WednesdayCodeChoice.SelectedValue % = 1 % & Model.WorkSchedules의 5b0 5d.ThursdayCodeChoice.SelectedValue % = 1 % & Model.WorkSchedules의 5b0 % 5d.FridayCodeChoice.SelectedValue = 1 모델 & .WorkSchedules % 5b0 % 5d.Saturday 모든 바인딩이 만들어집니다 : CodeChoice.SelectedValue = 1 & Model.WorkSchedules %의 5b0 % 5d.SundayCodeChoice.SelectedValue = 1 &는 ..... 나는 다음과 같은 사실이 있는지 만들었
ALL (12) NESTED VIEWMODELS} 계속 속성 (기본값. {get; set;}) BaseViewModel을 포함한 viewmodels에는 생성자가 없습니다.기본 생성자를 생성해야 함) 모든 속성 및 클래스는 public입니다.
그래서 ... 제 질문은 왜 모델 바인더가 목록의보기 모델을 만들 수 없습니까? 나는 다른 곳에서 템플릿을 사용하는 데 아무런 문제가 없다. 사람, 즉. 한 번에 하나의 행). 예, MVC 모델 바인딩과 관련된 많은 질문과 많은 답변이 있지만이 카테고리에 속하는 것은 거의 없습니다 (도서의 경우도 마찬가지 임). 실제로 나를 괴롭히는 것은 12 개 항목의 목록이 필요하다고 인식되지만 채워지지 않은 것입니다.
편집 :
public class BaseViewModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
var type = Type.GetType((string) typeValue.ConvertTo(typeof (string)), true);
if(!typeof(BaseViewModel).IsAssignableFrom(type))
throw new InvalidOperationException("NOT A BASEVIEWMODEL");
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}
[ModelBinder(typeof(BaseViewModelBinder))]
public class BaseViewModel
{
[HiddenInput]
public int Id { get; set; }
[HiddenInput]
public DateTime Created { get; set; }
[HiddenInput]
public DateTime Edited { get; set; }
public virtual string SelectionName { get; set; }
}
편집 2 :
[HttpPost]
public override async Task<JsonResult> Save(ItemViewModel item, string parentName, int? parentId)
{
if (item?.Model == null)
{
const int result = 0;
return Json(new { result });
}
var model = item.Model as WeekManagerWorkScheduleViewModel;
if (model == null)
{
const int result = 0;
return Json(new { result });
}
foreach (var inner in model.WorkSchedules)
{
}
return await base.Save(item, parentName, parentId);
}
public class ManagerWorkScheduleViewModel : BaseViewModel
{
[HiddenInput]
public int? ManagerId { get; set; }
[DisplayName("Leder")]
public string ManagerName { get; set; }
[HiddenInput]
public int? DateWeekId { get; set; }
[DisplayName("År/Uge")]
public string DateWeekText { get; set; }
[HiddenInput]
public int? MondayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Mandag")]
public ChoiceViewModel MondayCodeChoice { get; set; }
[HiddenInput]
public int? TuesdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Tirsdag")]
public ChoiceViewModel TuesdayCodeChoice { get; set; }
[HiddenInput]
public int? WednesdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Onsdag")]
public ChoiceViewModel WednesdayCodeChoice { get; set; }
[HiddenInput]
public int? ThursdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Torsdag")]
public ChoiceViewModel ThursdayCodeChoice { get; set; }
[HiddenInput]
public int? FridayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Fredag")]
public ChoiceViewModel FridayCodeChoice { get; set; }
[HiddenInput]
public int? SaturdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Lørdag")]
public ChoiceViewModel SaturdayCodeChoice { get; set; }
[HiddenInput]
public int? SundayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Søndag")]
public ChoiceViewModel SundayCodeChoice { get; set; }
}
오, btw, ASP.NET MVC 5를 사용하여 (내 생각 .. 그 중 하나는 전에 코어 :) – SayyesTono
당신은 파생 클래스를 사용할 수 없습니다. 관련 코드 (모델 또는 컨트롤러 메소드는 표시되지 않지만 'Model'속성이 BaseViewModel 유형 인 경우 DefaultModelBinder는'WeekManagerWorkScheduleViewModel' 및'WeekManagerWorkScheduleViewModel' 속성이 아닌'BaseViewModel'을 초기화합니다. 'BaseViewModel'에없는 것들은 무시 될 것입니다. –
ModelBinder 안에 브레이크 포인트를 넣으면 올바른 모델을 사용하고 또한 최상위 모델의 모든 속성 (숨겨진 입력 값)이 올바르게 생성되어 올바른 값이 주어집니다. 또한, BaseViewModel에서 파생 된 모든 viewmodels에 대한 매력처럼 작동합니다. – SayyesTono