Ядро aspnet, как публиковать данные из представления, если модель сложная

У меня есть проблемы с использованием методов Post в контроллерах ASP.NET Core MVC. Возможно, я использую неправильную архитектуру.

Имею 2 модели из БД.

     public class RecipeTable
    {
        public int Id { get; set; }
        public string MetrologyRecipe { get; set; }
        public string MetrologyTool { get; set; }
        //other properties
    }


    public class ParamTable
    {
        public int AupId { get; set; }
        public string ParamName{ get; set; }
        public string RecipeName { get; set; }
        public int? ParamOrderAuto { get; set; }
        //other properties
    }

И ящик для них. Потому что одна запись в RecipeTable связана с несколькими входами из ParamTable.

 public class FullModel
{
    public List<ParamTable> ParamRows ;
    public RecipeTable RecipeRow { set; get; }

    public FullModel()
    {
        ParamRows = new List<ParamTable> ();
    }

}

Для метода [Get] "Edit" это отлично работает.

[HttpGet]
    public async Task<IActionResult> Edit(int? id, string recipeName)
    {
        var fullModel = new FullModel();
        if (id == null) return NotFound();


        fullModel.RecipeRow = await 
        _context.RecipeTable.SingleOrDefaultAsync(m => m.Id == id);


        foreach (var row in _context.ParamTable)
            if (recipeName == row.RecipeName)
               fullModel.ParamRows.Add(row);



        if (fullModel.RecipeRow.MetrologyRecipe == null) return NotFound();
        return View(fullModel);
    }

Но для [Post] "Edit" это, конечно, не работает. Обновлена ​​только часть рецепта. Я не понимаю, как метод post получает данные из представления. Как работать с такими сложными моделями, когда нельзя менять базу данных и нельзя укажите подключение прямо в дизайнере базы данных.

 [HttpPost, ActionName("Edit")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, FullModel fullModel)
    {
        if (id != fullModel.RecipeRow.Id) return NotFound();

        if (ModelState.IsValid)
        {
            try
            {
                //**Here fullModel.ParamRows.Count = 0**
                _context.Update(fullModel.RecipeRow);
                await _context.SaveChangesAsync();
                foreach (var elem in fullModel.ParamRows)
                {
                    _context.Update(elem);
                    await _context.SaveChangesAsync();
                }

            }
            catch (DbUpdateConcurrencyException)
            {
                if (!RecipeTableExists(fullModel.RecipeRow.Id))
                    return NotFound();
                throw;
            }

            return RedirectToAction(nameof(Index));
        }

        return View(fullModel);

Часть вида выглядит так:

@model FullModel

@{
    ViewData["Title"] = "Edit";
}

<div class = "row">
    <div class = "col-md-4">
        <form asp-action = "Edit">
          

 <table class = "table" style = "margin-left: -50px">
                <thead>
                    <tr>
                        <th>Order</th>
                        <th>Param</th>
                    </tr>
                </thead>
                  <tbody>
                    @for (var i = 0; i < Model.ParamRows.Count; i++)
                    {
                        <tr>
                            <td>
                                <div class = "form-group">
                                    <input asp-for = "@Model.ParamRows[i].ParamOrderAuto" type = "text" class = "form-control" />
                                </div>
                            </td>
                            <td>
                                <div class = "form-group">
                                    <input  asp-for = "@Model.ParamRows[i].ParamName" class = "form-control" />
                                </div>
                            </td>
                         </tr>
                          }

                </tbody>
            </table>

            <div class = "form-group">
                <input type = "submit" value = "Save" class = "btn btn-default" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action = "Index">Back to List</a>
</div>
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
131
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы не можете использовать foreach для перебора ParamRows. Для того, чтобы привязщик моделей мог связать это обратно со списком в публикации, поля должны иметь такие имена, как ParamRows[N].ParamName. Используя foreach, вместо этого вы получите такие имена, как row.ParamName, которые моделиндер не распознает и просто отбросит.

Вместо этого используйте стандартный цикл for:

@for (var i = 0; i < Model.ParamRows.Count; i++)
{
    ...
    <input asp-for = "ParamRows[i].ParamName" />
    ...
}

В качестве альтернативы вы можете создать шаблон редактора для ParamTable, то есть ~/Views/Shared/EditorTemplates/ParamTable.cshtml, и поместить в него весь HTML (поля, метки и т. д.) Для редактирования экземпляра ParamTable. Затем вместо перебора элементов в ParamRows вы можете просто сделать:

@Html.EditorFor(m => m.ParamRows)

Razor автоматически перебирает каждый элемент и отображает шаблон редактора для каждого из них, давая каждому полю правильное имя для привязки.

Я попытался использовать ваше первое решение. Это сработало для имени поля, но ParamRows в FullModel по-прежнему не может быть упакован. Я думаю, что у меня проблема с привязкой модели или с боксом модели. Могу ли я отправить 2 модели в виде View (Model1, Model2)?

Denis Lightman 26.04.2018 10:36
Ответ принят как подходящий

У вас небольшая проблема с FullModel, нужно добавить методы get; set;. Просто исправьте вот так:

public class FullModel
{
    public List<ParamTable> ParamRows { get; set; };
    public RecipeTable RecipeRow { set; get; }
...

Другие вопросы по теме