Я новичок в ASP.NET MVC 5 (VS2013) и пытаюсь создать простую корзину покупок, где элементы можно добавлять и удалять.
Проблема, которую я имею, - это когда я нажимаю кнопку ADD, добавляемая строка не увеличивает идентификатор, как я ожидал. Он всегда возвращается как 0 (в HTML, который отображается в браузере), и, таким образом, кнопка удаления при нажатии удаляет все записи как следствие (все ID совпадают).
Я пытаюсь сделать это без AJAX и TempData/Session/ViewBag/ViewData, чтобы я мог лучше изучить привязку "автоматическая модель" (где размещенные значения привязаны к свойствам).
Контроллеры \ShoppingBasketController.cs
public class ShoppingBasketController : Controller
{
public ActionResult Index()
{
ShoppingBasketViewModel vm = new ShoppingBasketViewModel();
return View(vm);
}
[HttpPost]
public ActionResult Index(ShoppingBasketViewModel vm, string ButtonClicked)
{
if (ButtonClicked.ToLower() == "add")
{
return AddShoppingBasketItem(vm);
}
else if (ButtonClicked.ToLower().Contains("remove_"))
{
return RemoveShoppingBasketItem(vm, ButtonClicked);
}
else
{
return View(vm);
}
}
private ActionResult AddShoppingBasketItem(ShoppingBasketViewModel vm)
{
vm.Items.Add(new ShoppingBasketItemViewModel() { Id = vm.NextId, Name = String.Format("Name {0}", vm.NextId) });
vm.NextId++;
return View(vm);
}
private ActionResult RemoveShoppingBasketItem(ShoppingBasketViewModel vm, string WhichRemoveButtonClicked)
{
int idToDelete = 0;
bool success = int.TryParse(WhichRemoveButtonClicked.Split('_').LastOrDefault(), out idToDelete);
if (!success)
{
throw new ArgumentException("WhichRemoveButtonClicked", String.Format("Could not get Id to delete from the button clicked. '{0}", WhichRemoveButtonClicked));
}
vm.Items.RemoveAll(item => item.Id == idToDelete);
return View(vm);
}
}
Модели \ShoppingBasketViewModel.cs
public class ShoppingBasketViewModel
{
public int NextId { get; set; }
public List<ShoppingBasketItemViewModel> Items { get; set; }
public ShoppingBasketViewModel()
{
this.Items = new List<ShoppingBasketItemViewModel>();
}
}
Модели \ShoppingBasketItemViewModel.cs
public class ShoppingBasketItemViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
~/Views/Shared/DisplayTemplates/ShoppingBasketViewModel.cshtml
@model ShoppingBasketKyle.Models.ShoppingBasketViewModel
@* Format the rendered HTML to have line breaks *@
@Environment.NewLine
<table border="1">
<tr>
<td>ID</td>
<td>Name</td>
<td>Remove</td>
</tr>
@for (int count = 0; count < Model.Items.Count; count++)
{
<tr>
<td>@Html.DisplayFor(x => x.Items[count].Id)</td>
<td>@Html.DisplayFor(x => x.Items[count].Name)</td>
<td><input type="submit" name="ButtonClicked" value="[email protected](x => x.Items[count].Id)"/></td>
</tr>
}
</table>
@* Persist ShoppingBasketItems (Collection) property by posting them back *@
@for (int count = 0; count < Model.Items.Count; count++)
{
@Environment.NewLine
@Html.HiddenFor(x => x.Items[count].Id)
@Environment.NewLine
@Html.HiddenFor(x => x.Items[count].Name)
}
@* Persist the NextId property by posting it back *@
@Environment.NewLine
@Html.HiddenFor(x => x.NextId)
~/ShoppingBasket/Index.cshtml
@model ShoppingBasketKyle.Models.ShoppingBasketViewModel
@Html.ValidationSummary(true)
@using (Html.BeginForm())
{
@Html.DisplayForModel()
<input type="submit" name="ButtonClicked" value="Add" class="btn btn-primary btn--small" />
}
Любые вопросы, не стесняйтесь спрашивать
ТИА
рукав моря
Мне удалось разобраться в этом, но не понимаю, почему. Проблема, похоже, вызвана вспомогательным методом.HiddenFor() MVC. После поиска SO, похоже, что у него либо есть ошибка, либо по дизайну делает то, что вам неинтересно. Поэтому я обновляю следующее:
~/Views/Shared/DisplayTemplates/ShoppingBasketViewModel.cshtml
@model ShoppingBasketKyle.Models.ShoppingBasketViewModel
@* Format the rendered HTML to have line breaks *@
@Environment.NewLine
<table border="1">
<tr>
<td>ID</td>
<td>Name</td>
<td>Remove</td>
</tr>
@for (int count = 0; count < Model.Items.Count; count++)
{
<tr>
<td>@Html.DisplayFor(x => x.Items[count].Id)</td>
<td>@Html.DisplayFor(x => x.Items[count].Name)</td>
<td><input type="submit" name="ButtonClicked" value="[email protected](x => x.Items[count].Id)" /></td>
</tr>
}
@* Persist ShoppingBasketItems (Collection) property by posting them back *@
@for (int count = 0; count < Model.Items.Count; count++)
{
@Environment.NewLine
<input type="hidden" id="Items[@count.ToString()].Id" name="Items[@count.ToString()].Id" value="@Model.Items[count].Id" />
@Environment.NewLine
<input type="hidden" id="Items[@count.ToString()].Name" name="Items[@count.ToString()].Name" value="@Model.Items[count].Name" />
}
@* Persist the NextId property by posting it back *@
@Environment.NewLine
<input type="hidden" id="NextId" name="NextId" value="@Model.NextId" />
@Environment.NewLine
Я собираюсь написать метод extenstion, чтобы получить имя свойства viewmodel динамически, поэтому, если он будет переименован, мне не придется вручную поддерживать html в представлении
ура