Вопрос или проблема
Отправка POST-запроса с использованием ViewModel
Я создаю веб-сайт, на котором вы можете создать мероприятие для игры. У меня есть страница создания. На странице есть поле GameID при создании нового события. Я пытаюсь использовать модель представления (ViewModel), чтобы отображать название игры и выбирать его, вместо ID.
public class EventCreateVM
{
public Events Event { get; set; }
public IEnumerable<SelectListItem> Games { get; set; }
}
public class Events
{
public int EventID { get; set; }
public int GameID { get; set; }
[DisplayName("Название мероприятия")]
public string EventName { get; set; }
public string Server { get; set; }
[DisplayName("Максимальное количество игроков")]
public int MaxPlayers { get; set; }
public string Type { get; set; }
public string Platform { get; set; }
public string Description { get; set; }
[DisplayName("Время мероприятия")]
public DateTime DateTime { get; set; }
}
Я изменил страницу создания, чтобы она работала с моделью представления.
@model AgileTeamFour.UI.ViewModels.EventCreateVM
@{
ViewData["Title"] = "Создать";
}
<h1>Создать</h1>
<h4>Мероприятия</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" asp-controller="Event">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@* <div class="form-group">
<label asp-for="Event.EventID" class="control-label"></label>
<input asp-for="Event.EventID" class="form-control" />
<span asp-validation-for="Event.EventID" class="text-danger"></span>
</div> *@
<div class="form-group">
<label asp-for="Event.GameID" class="control-label"></label>
<select asp-for="Event.GameID" class="form-control" asp-items="Model.Games"></select>
<span asp-validation-for="Event.GameID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.EventName" class="control-label"></label>
<input asp-for="Event.EventName" class="form-control" />
<span asp-validation-for="Event.EventName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.Server" class="control-label"></label>
<input asp-for="Event.Server" class="form-control" />
<span asp-validation-for="Event.Server" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.MaxPlayers" class="control-label"></label>
<input asp-for="Event.MaxPlayers" class="form-control" />
<span asp-validation-for="Event.MaxPlayers" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.Type" class="control-label"></label>
<input asp-for="Event.Type" class="form-control" />
<span asp-validation-for="Event.Type" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.Platform" class="control-label"></label>
<input asp-for="Event.Platform" class="form-control" />
<span asp-validation-for="Event.Platform" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.Description" class="control-label"></label>
<input asp-for="Event.Description" class="form-control" />
<span asp-validation-for="Event.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Event.DateTime" class="control-label"></label>
<input asp-for="Event.DateTime" class="form-control" />
<span asp-validation-for="Event.DateTime" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Создать" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Назад к списку</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
И изменил контроллер.
public ActionResult Create()
{
var games = GameManager.Load();
var viewModel = new EventCreateVM
{
Event = new Events(),
Games = games.Select(g => new SelectListItem
{
Value = g.GameID.ToString(),
Text = g.GameName
}).ToList()
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(EventCreateVM viewmodel)
{
try
{
if (ModelState.IsValid)
{
int eventID = 0;
EventManager.Insert(ref eventID, viewmodel.Event.GameID, viewmodel.Event.EventName, viewmodel.Event.Server, viewmodel.Event.MaxPlayers, viewmodel.Event.Type, viewmodel.Event.Platform, viewmodel.Event.Description, viewmodel.Event.DateTime);
return RedirectToAction(nameof(Index));
}
return View(viewmodel);
}
catch
{
return View();
}
}
Страница корректно формирует список выбора игр. Но когда я нажимаю кнопку отправки, страница просто обновляется и ничего не создается в базе данных.
Форма, кажется, выглядит нормально, насколько я могу судить. Запрос возвращает 200, и, похоже, не возникает ошибок. Функция создания работает нормально, если я не использую изменения модели представления. Я пробовал несколько часов выяснить, в чем дело, но безуспешно. Буду благодарен за любой совет.
Судя по вашему коду, запрос отправляется на API “Event/Create” с GET вместо POST (метод HTTP), когда форма отправляется.
Вы можете отладить, установив точку останова в первой строке кода для обоих методов API “Event/Create” с GET
и POST
. Это поможет вам определить, попадает ли API “Event/Create” (с методом POST) в обработку.
В resumen, добавьте атрибут method="POST"
к элементу <form>
, чтобы убедиться, что форма отправляется на правильный API.
<form asp-action="Create" asp-controller="Event" method="POST">
...
</form>
Ответ или решение
При создании веб-сайта для планирования событий игр, вы столкнулись с проблемой, когда форма на странице создания события не обрабатывает POST-запрос правильно. Давайте разберем ваши шаги и предложим решение.
Проблема
Вы создали контроллер и представление, использующие ViewModel
, и всё выглядело нормально: список игр формируется корректно, но после нажатия кнопки отправки происходит только обновление страницы и события не создаются в базе данных. Это может быть связано с тем, что форма не отправляется с методом POST.
Решение
-
Проверьте метод формы: Убедитесь, что ваша форма действительно использует метод POST. Для этого добавьте атрибут
method="POST"
к вашему элементу<form>
:<form asp-action="Create" asp-controller="Event" method="POST"> ... </form>
-
Отладка: Чтобы убедиться, что метод
Create
с POST запросом вызывается, вы можете установить точки останова в начале методовCreate
в контроллере. Это поможет вам определить, получает ли ваш контроллер запрос. -
Проверка состояния модели: Убедитесь, что модель проходит валидацию перед вставкой данных в базу. Для этого вам нужно убедиться, что все обязательные поля заполнены и соответствуют заданным требованиям. Если валидация не проходит, данные не будут добавлены в базу:
if (ModelState.IsValid) { // Вставка данных } else { // Верните обратно ту же ViewModel с ошибками return View(viewmodel); }
- Логи ошибок: Если данные не добавляются, вам следует рассмотреть возможность ведения логов ошибок. Это поможет вам зафиксировать любые исключения или проблемы, возникающие при вставке данных в базу. Например:
catch (Exception ex) { // Логируйте ошибку // return View(viewmodel); }
Полный Пример
Примените изменения, как показано ниже:
<form asp-action="Create" asp-controller="Event" method="POST">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Event.GameID" class="control-label"></label>
<select asp-for="Event.GameID" class="form-control" asp-items="Model.Games"></select>
<span asp-validation-for="Event.GameID" class="text-danger"></span>
</div>
<!-- Другие поля формы -->
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Заключение
После внесения всех вышеуказанных изменений повторите попытку отправить форму. Убедитесь, что все поля формы заполнены правильно, и проверьте, срабатывает ли метод POST
в контроллере. Если проблема сохраняется, вам стоит проверить логи и отладить данные, отправляемые с формы. Удачи!