Редактирование элемента в представлении индекса отменяет привязку модели. Как заставить это работать?

Я пытаюсь создать систему, в которой пользователь может щелкнуть элемент в списке, а затем отредактировать этот элемент, оставаясь в представлении Index.

Моя попытка представляет собой просто смесь между Index.cshtml и Edit.cshtml:

@model IEnumerable<MyStore.Models.ProductIdentifier>
@{int primary_id = (this.ViewContext.RouteData.Values["primary_id"] != null
        ? int.Parse(this.ViewContext.RouteData.Values["primary_id"].ToString())
        : 0);
}
@foreach (var item in Model)
{
    if (item.Id == primary_id)
    {
        // This list-item is editable (copied from Edit.cshtml):
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="@item.Id" />
            <div class="form-group col-lg-4">
                <input asp-for="@item.Label" class="form-control" />
                <span asp-validation-for="@item.Label" class="text-danger"></span>
            </div>
            <div class="form-group col-lg-6">
                <input asp-for="@item.Description" class="form-control" />
                <span asp-validation-for="@item.Description" class="text-danger"></span>
            </div>
            <div class="form-group col-lg-1">
                <input asp-for="@item.SortOrder" class="form-control" />
                <span asp-validation-for="@item.SortOrder" class="text-danger"></span>
            </div>
            <div class="form-group col-lg-1">
                <button type="submit" value="Save" class="btn btn-primary">
                    <span class="glyphicon glyphicon-floppy-disk"></span> Save
                </button>
            </div>
        </form>
    }
    else
    {
        // This list-item is just a plain list-item:
        <div class="row table">
            <div class="col-lg-4">
                <a asp-action="Index" asp-route-primary_id="@item.Id">
                    @Html.DisplayFor(modelItem => item.Label)
                </a>
            </div>
            <div class="col-lg-6">
                @Html.DisplayFor(modelItem => item.Description)
            </div>
            <div class="col-lg-1">
                @Html.DisplayFor(modelItem => item.SortOrder)
            </div>
            <div class="col-lg-1">
                <a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-xs btn-danger">
                    <span class="glyphicon glyphicon-trash"></span>
                </a>
            </div>
        </div>
    }
}

Предполагается, что данные формы будут отправлены в метод Edit в контроллере:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Label,Description,SortOrder")] ProductIdentifier productIdentifier)
{
    if (id != productIdentifier.Id) { return NotFound(); }
    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(productIdentifier);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ProductIdentifierExists(productIdentifier.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(productIdentifier);
}

... но поскольку мне пришлось добавить @item. перед элементами в форме (поскольку модель представляет собой IEnumerable, и я хочу опубликовать только один объект), привязка модели больше не работает, и объект null создается опубликовано.

Как я могу заставить его работать?


person Stian    schedule 22.02.2018    source источник


Ответы (1)


Я заставил это работать!

Во-первых, я создал ViewModel, который содержит как ICollection идентификаторов, так и один экземпляр идентификатора:

public class ViewModelEditIdentifierInIndexView
{
    public ViewModelProductIdentifier SingleItem { get; set; }
    public ICollection<ViewModelProductIdentifier> ListOfItems { get; set; }
}

Мне пришлось внести некоторые изменения в метод Index в контроллере, чтобы учесть модель представления:

public async Task<IActionResult> Index(int? primary_id)
    {
        ProductIdentifier pi = await _context.ProductIdentifiers
                                .Where(i => i.Id == primary_id)
                                .SingleOrDefaultAsync();
        ViewModelEditIdentifierInIndexView ViewModel = new ViewModelEditIdentifierInIndexView
        {
            SingleItem = _mapper.Map<ViewModelProductIdentifier>(pi),
            ListOfItems = _mapper.Map<ICollection<ViewModelProductIdentifier>>(await _context.ProductIdentifiers.ToListAsync())
        };
        return View(ViewModel);
    }

Затем я изменил модель в представлении Index:

@model MyStore.Models.ViewModels.ViewModelEditIdentifierInIndexView

Затем я изменил форму редактирования. Наиболее важным изменением является добавление name-тегов к каждому input-полю:

<form asp-action="Edit">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="SingleItem.Id" name="Id" />
    <div class="form-group col-lg-4" style="padding-left:0px;">
        <input asp-for="SingleItem.Label" name="Label" class="form-control" />
        <span asp-validation-for="SingleItem.Label" class="text-danger"></span>
    </div>
    <div class="form-group col-lg-6" style="padding-left:0px;">
        <input asp-for="SingleItem.Description" name="Description" class="form-control" />
        <span asp-validation-for="SingleItem.Description" class="text-danger"></span>
    </div>
    <div class="form-group col-lg-1" style="padding-left:0px;">
        <input asp-for="SingleItem.SortOrder" name="SortOrder" class="form-control" />
        <span asp-validation-for="SingleItem.SortOrder" class="text-danger"></span>
    </div>
    <div class="form-group col-lg-1" style="padding-left:0px;">
        <button type="submit" value="Save" class="btn btn-xs btn-success">
            <span class="glyphicon glyphicon-floppy-disk"></span>
        </button>
        <a href="/Admin/ProductIdentifiers" class="btn btn-xs btn-warning">
            <span class="glyphicon glyphicon-chevron-left"></span>
        </a>
    </div>
</form>

Мне не нужно было вносить какие-либо изменения в метод Edit в контроллере.

person Stian    schedule 22.02.2018