C # ASP.NET MVC Вернуться на предыдущую страницу - PullRequest
64 голосов
/ 19 марта 2012

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

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

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

ViewBag.ReturnUrl = Request.UrlReferrer;

Затем я отправил этот обратный URL-адрес в метод «Редактировать сообщение», используя мой тег формы, например:

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

Теперь здесь упали колеса. Я не смог получить URL, разобранный по параметру id должным образом.

*** ОБНОВЛЕНИЕ: РЕШЕНО ***

Используя пример Гарри в качестве руководства, я изменил свой параметр с «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 из модели в метод [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);
    }

Ответы [ 2 ]

53 голосов
/ 19 марта 2012

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

Возможно, вам повезет большепросто вернув представление снова, а не пытаясь перенаправить пользователя, таким образом вы сможете использовать 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-адрес с обратным путем.

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

0 голосов
/ 11 июля 2019

Вот еще один вариант, который вы можете применить для 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>

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

...