Отправьте один и тот же частичный просмотр,вызванный многократными данными в контроллер.

asp.net-mvc-4


Я добавил кнопку на мой взгляд.При нажатии на эту кнопку добавляется частичный вид.В моей форме я могу добавить как можно больше частичного вида.При отправке данных этой формы я не могу отправить все данные частичного вида контроллеру.Я создал другую модель,имеющую все атрибуты,и составил список этой модели для своей основной модели.Может ли кто-нибудь,пожалуйста,дать мне какой-нибудь трюк,чтобы я мог отправить все данные частичного вида на контроллер?

На мой взгляд

<div id="CSQGroup">   
</div>
<div>
  <input type="button" value="Add Field" id="addField" onclick="addFieldss()" />
</div>

function addFieldss()
{    
  $.ajax({
    url: '@Url.Content("~/AdminProduct/GetColorSizeQty")',
    type: 'GET',
    success:function(result) {
      var newDiv = $(document.createElement("div")).attr("id", 'CSQ' + myCounter);  
      newDiv.html(result);
      newDiv.appendTo("#CSQGroup");
      myCounter++;
    },
    error: function(result) {
      alert("Failure");
    }
  });
}

В моем контроллере

public ActionResult GetColorSizeQty()
{
  var data = new AdminProductDetailModel();
  data.colorList = commonCore.getallTypeofList("color");
  data.sizeList = commonCore.getallTypeofList("size");
  return PartialView(data);
}

[HttpPost]
public ActionResult AddDetail(AdminProductDetailModel model)
{
  ....
}

В моем частичном представлении

@model IKLE.Model.ProductModel.AdminProductDetailModel
<div class="editor-field">
  @Html.LabelFor(model => model.fkConfigChoiceCategorySizeId)
  @Html.DropDownListFor(model => model.fkConfigChoiceCategorySizeId, Model.sizeList, "--Select Size--")
  @Html.ValidationMessageFor(model => model.fkConfigChoiceCategorySizeId)
</div>
<div class="editor-field">
  @Html.LabelFor(model => model.fkConfigChoiceCategoryColorId)
  @Html.DropDownListFor(model => model.fkConfigChoiceCategoryColorId, Model.colorList, "--Select Color--")
  @Html.ValidationMessageFor(model => model.fkConfigChoiceCategoryColorId)
</div>   
<div class="editor-field">
  @Html.LabelFor(model => model.productTotalQuantity)
  @Html.TextBoxFor(model => model.productTotalQuantity)
  @Html.ValidationMessageFor(model => model.productTotalQuantity)
</div>




Answer 1 Community


Ваша проблема заключается в том, что частичное AdminProductDetailModel html основано на одном объекте AdminProductDetailModel , но вы пытаетесь отправить обратно коллекцию. Когда вы динамически добавляете новый объект, вы продолжаете добавлять дубликаты элементов управления, которые выглядят как <input name="productTotalQuantity" ..> (это также создает недопустимый html из-за дублированных атрибутов id ), где они должны быть <input name="[0].productTotalQuantity" ..> , <input name="[1].productTotalQuantity" ..> и т. Д., Чтобы связать коллекцию с обратной связью.

DefaultModelBinder требуется, чтобы индексатор для элементов коллекции начинаются с нуля и быть последовательными, или что значения формы включают в себя Index=someValue , где индексатор someValue (например , <input name="[ABC].productTotalQuantity" ..><input name="Index" value="ABC"> . Это подробно объясняется в статье Фила Хаака « Привязка модели к списку» . Использование подхода «Индекс», как правило, лучше, поскольку позволяет также удалять элементы из списка (в противном случае это будет необходимо переименовать все существующие элементы управления, чтобы индексатор работал последовательно).

Два возможных подхода к вашему вопросу.

Опция 1

Используйте помощник BeginItemCollection для частичного просмотра. Этот помощник будет отображать скрытый ввод для значения Index на основе GUID. Это необходимо как в частичном представлении, так и в цикле, в котором вы визуализируете существующие элементы. Ваш частичный будет выглядеть примерно так

@model IKLE.Model.ProductModel.AdminProductDetailModel
@using(Html.BeginCollectionItem()) 
{
  <div class="editor-field">
    @Html.LabelFor(model => model.fkConfigChoiceCategorySizeId)
    @Html.DropDownListFor(model => model.fkConfigChoiceCategorySizeId, Model.sizeList, "--Select Size--")
    @Html.ValidationMessageFor(model => model.fkConfigChoiceCategorySizeId)
  </div>
  ....
}

Вариант 2

Вручную создайте элементы html, представляющие новый объект с помощью «поддельного» индексатора, поместите их в скрытый контейнер, затем в событии кнопки «Добавить», клонируйте HTML, обновите индексаторы и значение индекса и добавьте клонированные элементы в DOM. Чтобы убедиться, что html верен, создайте один объект по умолчанию в цикле for и проверьте html, который он генерирует. Пример такого подхода показан в этом ответе

<div id="newItem" style="display:none">

  <div class="editor-field">
    <label for="_#__productTotalQuantity">Quantity</label>
    <input type="text" id="_#__productTotalQuantity" name="[#].productTotalQuantity" value />
    ....
  </div>
  // more properties of your model
</div>

Обратите внимание на использование «фальшивого» индексатора для предотвращения его привязки к обратной записи («#» и «%» не совпадают, поэтому DefaultModelBinder их игнорирует )

$('#addField').click(function() {
  var index = (new Date()).getTime(); 
  var clone = $('#NewItem').clone();
  // Update the indexer and Index value of the clone
  clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
  clone.html($(clone).html().replace(/"%"/g, '"' + index  + '"'));
  $('#yourContainer').append(clone.html());
}

Преимущество варианта 1 заключается в том,что вы сильно набираете вид для вашей модели,но это означает звонок на сервер каждый раз,когда вы добавляете новый элемент.Преимущество варианта 2 заключается в том,что все это делается на клиентской стороне,но если вы вносите какие-либо изменения в свою модель (например,добавляете атрибут валидации в свойство),то вам также необходимо вручную обновить html,что немного усложняет обслуживание.

Наконец, если вы используете проверку на стороне клиента (jquery-validate-unobtrusive.js), то вам необходимо повторно анализировать валидатор каждый раз, когда вы добавляете новые элементы в DOM, как объяснено в этом ответе .

$('form').data('validator', null);
$.validator.unobtrusive.parse($('form'));

И,конечно же,вам нужно изменить метод POST,чтобы принять коллекцию.

[HttpPost]
public ActionResult AddDetail(IEnumerable<AdminProductDetailModel> model)
{
  ....
}