У меня есть проблемы с использованием методов 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>




Вы не можете использовать 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 автоматически перебирает каждый элемент и отображает шаблон редактора для каждого из них, давая каждому полю правильное имя для привязки.
У вас небольшая проблема с FullModel, нужно добавить методы get; set;. Просто исправьте вот так:
public class FullModel
{
public List<ParamTable> ParamRows { get; set; };
public RecipeTable RecipeRow { set; get; }
...
Я попытался использовать ваше первое решение. Это сработало для имени поля, но ParamRows в FullModel по-прежнему не может быть упакован. Я думаю, что у меня проблема с привязкой модели или с боксом модели. Могу ли я отправить 2 модели в виде View (Model1, Model2)?