Перенаправить на метод действия GET из метода действия POST в. NET MVC - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь создать веб-приложение для отслеживания лекарств для пациентов в аптеках, используя EF CORE и MVC, но столкнулся с проблемой. У меня есть представление, настроенное для создания сценария с использованием базовых CRUD-операций, которое работает нормально, но я не пытаюсь реализовать дополнительную функциональность. В частности, я хочу возможность добавлять несколько элементов в один скрипт. Моя БД и существующие представления обновлены, но я пытаюсь найти лучший способ сделать эту работу.

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

Есть ли в моем контроллере способ перенаправления из действия post обратно в действие get и одновременной передачи нескольких параметров?

GET action

        [HttpGet]
        public async Task<IActionResult> Create(
            int id,
            string sort,
            string currentFilter,
            string search,
            int? pageNumber)
        {
            ViewData["NameSortParam"] = String.IsNullOrEmpty(sort) ? "name_desc" : "";
            ViewData["PackSortParam"] = sort == "pack" ? "pack_desc" : "pack";
            ViewData["GenSortParam"] = sort == "gen" ? "gen_desc" : "gen";
            ViewData["StockSortParam"] = sort == "stock" ? "stock_desc" : "stock";
            ViewData["CurrentSort"] = sort;

            if (!String.IsNullOrEmpty(search))
            {
                pageNumber = 1;
            }
            else
            {
                search = currentFilter;
            }

            ViewData["CurrentFilter"] = search;


            var drugs = from drug in _context.Drug
                        join generic in _context.Generic on drug.GenericId equals generic.Id
                        select drug;

            if (!String.IsNullOrEmpty(search))
            {
                drugs = drugs.Where(d => d.Name.Contains(search)
                                || d.Generic.Name.Contains(search));
            }

            switch (sort)
            {
                case "name_desc":
                    drugs = drugs.OrderByDescending(d => d.Name);
                    break;
                case "pack":
                    drugs = drugs.OrderBy(d => d.PackSize);
                    break;
                case "pack_desc":
                    drugs = drugs.OrderByDescending(d => d.PackSize);
                    break;
                case "cost":
                    drugs = drugs.OrderBy(d => d.CostPrice);
                    break;
                case "cost_desc":
                    drugs = drugs.OrderByDescending(d => d.CostPrice);
                    break;
                case "gen":
                    drugs = drugs.OrderBy(d => d.Generic.Name);
                    break;
                case "gen_desc":
                    drugs = drugs.OrderByDescending(d => d.Generic.Name);
                    break;
                case "stock":
                    drugs = drugs.OrderBy(d => d.StockQty);
                    break;
                case "stock_desc":
                    drugs = drugs.OrderByDescending(d => d.StockQty);
                    break;
                default:
                    drugs = drugs.OrderBy(d => d.Name);
                    break;
            }

            drugs = drugs.Include(d => d.Generic);

            int pageSize = 5;

            var patient = await _context.Patient.FindAsync(id);

            var vm = new NewScriptViewModel()
            {
                Patient = patient,
                PatientId = patient.Id,
                Prescribers = await _context.Prescriber.ToListAsync(),
                Drugs = await PaginatedList<Drug>.CreateAsync(drugs.AsNoTracking(), pageNumber ?? 1, pageSize)

            };
            ViewData["PrescriberId"] = new SelectList(_context.Prescriber, "Id", "FullName", patient.PrescriberId);


            return View(vm);
        }

Действие POST - добавить следующий элемент в тот же сценарий

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(bool FirstItem, [Bind("PatientId, PrescriberId")] Script script, [Bind("DrugId, Qty, Directions")] ScriptDrug scriptDrug)
        {
            if (ModelState.IsValid)
            {
                if (FirstItem)
                {
                    //create script
                    _context.Add(script);
                    await _context.SaveChangesAsync();

                    //add item
                    scriptDrug.ScriptId = script.Id;
                    var drug = _context.Drug.Find(scriptDrug.DrugId);
                    drug.StockQty -= scriptDrug.Qty;
                    _context.Add(scriptDrug);
                    await _context.SaveChangesAsync();

                    //redirect to create to add new item to same script

                }
            }
            //redirect back to view
        }

Надеюсь, я объяснил это адекватно, но дайте мне знать, если мне потребуется предоставить какие-либо дополнительные информация.

Примечание: модель просмотра

    public class NewScriptViewModel

    {
        public int ScriptId { get; set; }
        public Patient Patient { get; set; }
        public int PatientId { get; set; }
        public IEnumerable<Prescriber> Prescribers { get; set; }
        public int PrescriberId { get; set; }
        public PaginatedList<Drug> Drugs { get; set; }
        public int DrugId { get; set; }
        public int Qty { get; set; }
        public string Directions { get; set; }
        public bool FirstItem { get; set; }

        public NewScriptViewModel()
        {
            FirstItem = true;
        }
    }

1 Ответ

0 голосов
/ 04 марта 2020

Добро пожаловать в StackOverflow, эзотерический боб!

Да, Post/Redirect/Get - это очень распространенный и очень желаемый шаблон. Это может помешать Вам или Вашим пользователям случайно инициировать один и тот же запрос POST дважды. Если Вы уже знаете это, извините, просто для пояснения.

Я создал небольшой пример для Вас, надеюсь, это то, что Вы ищете:

HomeController. cs

namespace WebApplication4.Controllers
{
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using WebApplication4.Models;

    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IActionResult Index()
        {
            return View(new MyModel());
        }

        [HttpPost]
        public IActionResult Index(MyModel model)
        {
            ViewBag.additionalData = "Something";
            return View();
        }
    }
}

Home \ Index.cs html

@model MyModel

Get view

<form method="post">
    <input asp-for="@Model.Data" />
    <button type="submit">Post!</button>
</form>

Additional data: @ViewBag.additionalData

MyModel.cs

namespace WebApplication4.Models
{
    public class MyModel
    {
        public string Data { get; set; }
    }
}

Рабочий процесс выглядит следующим образом:

  • Начните с [GET] Home\Index. Мы окажемся в методе [GET] Index.
  • return View(new MyModel()); вернет нам Views\Home\Index.cshtml (по соглашению) с новой пустой моделью для заполнения формой.
  • we заполните значения формы, отправьте данные с помощью метода POST (без атрибутов action или controller в теге <form>, так как условно он отправит [POST] Home\Index и доставит нас к тому же контроллеру и тому же названному действию, но POST версия на нем)
  • мы используем ViewBag для хранения дополнительных данных для вызова
  • , затем мы вызываем просто View() для вызова Home\Index (опять-таки по соглашению вызывающий контроллер с тем же имя и представление совпадают с именем метода)
  • по умолчанию он запросит еще [GET] Home\Index, и мы вернемся к тому, с чего начали, но с некоторым дополнительным значением для использования внутри ViewBag (которое исчезнет, ​​если мы redirect / refre sh).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...