Подтвердить что ты не робот

С# ASP.NET MVC Вернуться на предыдущую страницу

У меня есть базовый метод Edit в моем контроллере, который перенаправляет обратно на листинг верхнего уровня ( "Индекс" ), когда редактирование завершается успешно. Стандартное поведение после строительных лесов MVC.

Я пытаюсь изменить этот метод Edit для перенаправления на предыдущую страницу (а не на индекс). Поскольку мой метод "Редактировать" не использовал введенный по умолчанию входной параметр "id" , я сначала попытался использовать это, чтобы передать предыдущий URL.

В моем методе "get get" я использовал эту строку, чтобы захватить предыдущий URL-адрес, и он работал нормально:

ViewBag.ReturnUrl = Request.UrlReferrer;

Затем я отправил этот возвращаемый URL-адрес методу "post", используя мой тег формы следующим образом:

@using (Html.BeginForm(new { id = ViewBag.ReturnUrl }))

Теперь это то, где колеса отвалились. Я не смог правильно проанализировать URL-адрес из параметра id.

*** UPDATE: SOLVED ***

Используя пример Garry в качестве руководства, я изменил свой параметр с "id" на "returnUrl" и использовал скрытое поле для передачи моего параметра (вместо тега формы). Извлеченный урок: используйте параметр "id" , как он должен был использоваться, и сохраняйте его простым. Он работает сейчас. Вот мой обновленный код с примечаниями:

Сначала я беру предыдущий URL-адрес с помощью Request.UrlReferrer, как и в первый раз.

    //
    // GET: /Question/Edit/5

    public ActionResult Edit(int id)
    {
        Question question = db.Questions.Find(id);
        ViewBag.DomainId = new SelectList(db.Domains, "DomainId", "Name", question.DomainId);
        ViewBag.Answers = db.Questions
                            .AsEnumerable()
                            .Select(d => new SelectListItem
                            {
                                Text = d.Text,
                                Value = d.QuestionId.ToString(),
                                Selected = question.QuestionId == d.QuestionId
                            });
        // Grab the previous URL and add it to the Model using ViewData or ViewBag
        ViewBag.returnUrl = Request.UrlReferrer;
        ViewBag.ExamId = db.Domains.Find(question.DomainId).ExamId;
        ViewBag.IndexByQuestion = string.Format("IndexByQuestion/{0}", question.QuestionId);
        return View(question);
    }

и теперь я передаю параметр returnUrl из метода Model в метод [HttpPost], используя скрытое поле в форме:

@using (Html.BeginForm())
{
    <input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />
    ...

В методе [HttpPost] мы вытаскиваем параметр из скрытого поля и перенаправляем его....

    //
    // POST: /Question/Edit/5

    [HttpPost]
    public ActionResult Edit(Question question, string returnUrl) // Add parameter
    {
        int ExamId = db.Domains.Find(question.DomainId).ExamId;
        if (ModelState.IsValid)
        {
            db.Entry(question).State = EntityState.Modified;
            db.SaveChanges();
            //return RedirectToAction("Index");
            return Redirect(returnUrl);
        }
        ViewBag.DomainId = new SelectList(db.Domains, "DomainId", "Name", question.DomainId);
        return View(question);
    }
4b9b3361

Ответ 1

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

Возможно, вам повезет больше, просто вернув представление снова, а не пытаясь перенаправить пользователя. Таким образом, вы сможете использовать ModelState и для вывода любых ошибок.

Редактировать:

Обновлено на основе отзывов. Вы можете поместить предыдущий URL в viewModel, добавить его в скрытое поле и затем использовать его снова в действии, которое сохраняет изменения.

Например:

public ActionResult Index()
{
    return View();
}

[HttpGet] // This isn't required
public ActionResult Edit(int id)
{
   // load object and return in view
   ViewModel viewModel = Load(id);

   // get the previous url and store it with view model
   viewModel.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;

   return View(viewModel);
}

[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
   // Attempt to save the posted object if it works, return index if not return the Edit view again

   bool success = Save(viewModel);
   if (success)
   {
       return Redirect(viewModel.PreviousUrl);
   }
   else
   {
      ModelState.AddModelError("There was an error");
      return View(viewModel);
   }
}

Метод BeginForm для вашего представления также не должен использовать этот обратный URL, вы должны иметь возможность сойти с рук:

@model ViewModel

@using (Html.BeginForm())
{
    ...
    <input type="hidden" name="PreviousUrl" value="@Model.PreviousUrl" />
}

Возвращаясь к публикации действий с неправильным URL-адресом, это происходит потому, что вы передаете URL-адрес в качестве параметра 'id', поэтому маршрутизация автоматически форматирует ваш URL-адрес с помощью пути возврата.

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

Ответ 2

Вот еще один вариант, который вы можете применить для ASP NET MVC.

Обычно вы должны использовать класс BaseController для каждого класса Controller.

Так внутри метода конструктора сделайте следующее.

public class BaseController : Controller
{
        public BaseController()
        {
            // get the previous url and store it with view model
            ViewBag.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
        }
}

И теперь в ЛЮБОМ представлении вы можете сделать как

<button class="btn btn-success mr-auto" onclick="  window.location.href = '@ViewBag.PreviousUrl'; " style="width:2.5em;"><i class="fa fa-angle-left"></i></button>

Наслаждайтесь!