Подтвердить что ты не робот

Отправить один и тот же Partial View, называемый несколько раз данными для контроллера?

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

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

<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>
4b9b3361

Ответ 1

Ваша проблема заключается в том, что частичный рендеринг 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">. Это подробно объяснено в статье Фила Хаака привязка модели к списку. Использование подхода Index обычно лучше, потому что оно также позволяет удалять элементы из списка (в противном случае это необходимо было бы переименовать все существующие элементы управления, чтобы индексчик был последовательным).

Два возможных подхода к вашей проблеме.

Вариант 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)
{
  ....
}