Метод контроллера пропускает представление возврата - PullRequest
0 голосов
/ 13 июля 2020

Я новичок в MVC и впервые имею дело с ViewModels, поэтому у меня возникли небольшие трудности.

У меня есть страница просмотра, где пользователь выбирает, хотят ли они собирать урожай / передать / избавиться от детали. Затем эти данные сохраняются в ViewModel. Затем я хочу представить пользователю сводную страницу того, что они выбрали. Поэтому я пытаюсь добиться этого, выполнив следующее.

В моем методе POST я пытаюсь вызвать страницу получения сводки

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SpecialOrderSelection(JobOrder job, ItemViewModel model)
{               
   if (ModelState.IsValid)
   {
      JobOrder jobOrder = db.JobOrders.Find(job.ID);
      if (jobOrder == null)
      {
         return HttpNotFound();
      }
      ViewBag.JobOrderID = jobOrder.ID;
   }  

  return SpecialOrderSummary(model);
}

Это правильно вызывает метод получения сводки

public ActionResult SpecialOrderSummary(ItemViewModel model)
{
   if (model == null)
   {
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
   }

   JobOrder jobOrder = db.JobOrders.Find(model.ID);
   if (jobOrder == null)
   {
      return HttpNotFound();
   }

  return View(model);
}

Вот фрагмент страницы просмотра, которую я пытаюсь вернуть

@model PIC_Program_1._0.Models.ItemViewModel
@using PIC_Program_1._0.Models
@{
    ViewBag.Title = "SpecialOrderSummary";
}

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(x => x.ID)
    <h2>Special Order Summary</h2>
    <p style="color:red" class="noprint">Please review and verify </p>


    <h2>
        Transfers
    </h2>
    <h4><b>Components </b></h4>
    <table class="table">

        <tr>
            <th>
                IGT Component ID
            </th>
            <th>
                MFG ID
            </th>
            <th>
                Component Name
            </th>
        </tr>

        @foreach (var comp in Model.Components.Where(n => n.SelectedActionType == PartActionType.Transfer))
        {
            <tr>
                <td> @comp.ComponentId</td>
                <td> @comp.MFGNumber</td>
                <td> @comp.ComponentName</td>
            </tr>
        }
    </table>
}

Вот моя ViewModel

 public class ItemViewModel
    {
        [Required]
        public int ID { get; set; }
        public string ItemId { get; set; }
        public string ItemName { get; set; }
        public string MFGNumber { get; set; }
        public IList<ItemPartViewModel> Parts { get; set; }
        public IList<ItemComponentViewModel> Components{ get; set; }
        public IList<ComponentPartViewModel> ComponentParts { get; set; }
        public IList<ComponentSubCompViewModel> ComponentSubComps { get; set; }
        public IList<SubCompPartViewModel> SubCompParts { get; set; }

        public IList<SubCompSubCompViewModel> SubCompSubComps { get; set; }
        public IList<SubCompSubCompPartViewModel> SubCompSubCompParts { get; set;}

    }

Модель надлежащим образом передается в GET, но пропускается поверх моего return View(model) и вместо этого возвращает страницу просмотра «Выбор», а не страницу просмотра «Сводка».

Как я могу это исправить?

Ответы [ 2 ]

2 голосов
/ 13 июля 2020

Это не то, как вы это делаете:

return SpecialOrderSummary(model);

Хотя этот будет в конечном итоге вызвать return View(model) из другого метода, в конечном итоге вы возвращаете View изнутри SpecialOrderSelection, и фреймворк использует это, чтобы определить, какое представление отображать. Это укажет браузеру сделать новый запрос GET на SpecialOrderSummary, передав значение ID того, что содержится в jobOrder.ID. (Я предполагаю, что это именно тот идентификатор, который вам нужен, если не просто заменить его тем, что вам нужно.)

1 голос
/ 13 июля 2020

Вы просто запутались с моделью просмотра. Модель представления не имеет особого значения. Это просто POCO (обычный старый объект CLR), который содержит ТОЛЬКО информацию, которую вам нужно отображать в представлении, а не действия, не события. Он служит контейнером между контроллерами и представлениями.

Опять же, я не знаю домен, над которым вы работаете, поэтому я предполагаю следующее:

Возможно, вы уже извлекли данные из базы данных и построили эту модель представления с помощью метода GET. Если вы хотите сохранить, например, JobID, вам необходимо объявить свойство в модели представления и поместить его в скрытую форму в вашем представлении, чтобы при отправке формы обратно оно сохранялось.

public class ItemViewModel
{
    [Required]
    public int JobId { get; set; }

    public string ItemId { get; set; }
    ...
}

Вам также необходимо указать метод и контроллер, который ваша форма отправляет обратно:

@using (Html.BeginForm("specialOrderSelection", "WhatEverController", new { area = "" }, 
    FormMethod.Post))
{
    @Html.AntiForgeryToken()

    @Html.HiddenFor(x => x.JobId)
    <h2>Special Order Summary</h2>

Затем в вашем методе POST он должен принимать только один параметр - модель представления, поскольку она должна иметь все, что вам нужно:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SpecialOrderSelection(ItemViewModel model)
{               
   if (ModelState.IsValid)
   {
      JobOrder jobOrder = db.JobOrders.Find(model.JobId);
      if (jobOrder == null)
      {
         return HttpNotFound();
      }

      // Do your logic to save anything you want to your database
   }  

  return RedirectionToAction("summary", new { jobId = model.JobId });
}

В конце он перенаправляет на действие «Сводка» в том же контроллере с идентификатором задания (или другим идентификатором ключа для идентификации ваших объектов). Вы снова получаете данные с идентификатором:

public ActionResult Summary(int jobId)
{
    // Fetch the data again with the ID, and fill the view model
    // ...

    var vm = new SpecialOrderViewModel
    {
        ...
    };

    return View(vm);
}

Там у вас должна быть другая модель представления и представление только для сводной страницы.

...