C # ASP.NET MVC Повернутися на попередню сторінку


74

У моєму контролері є основний метод редагування, який переспрямовує назад до списку верхнього рівня (“Індекс”), коли редагування вдається. Стандартна поведінка після будівельних лісів MVC.

Я намагаюся змінити цей метод редагування, щоб перенаправити назад на попередню сторінку (не в Індекс). Оскільки в моєму методі редагування не використовувався відображений вхідний параметр за замовчуванням “id”, я спочатку спробував використати його для передачі в попередній URL-адресі.

У моєму методі редагування “get” я використав цей рядок, щоб захопити попередню URL-адресу, і вона працювала нормально:

ViewBag.ReturnUrl = Request.UrlReferrer;

Потім я надіслав цю зворотну URL-адресу методу редагування “post”, використовуючи мій тег форми так:

@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);
    }

1
Навіть якщо ви не використовуєте id, я б не використовував його для передачі URL-адреси. Це здається хакерством, і я впевнений, що є кращий спосіб це зробити.
Ерік Андрес

Так, Eirc, ти маєш рацію. Я використовував потворний хак. Це мій перший додаток MVC. Я спробував багато речей і прочитав багато постів, і хак був моєю найкращою спробою. Я виправив це на прикладі Гері. Дякую,
Джейсон Енокс,

Відповіді:


63

Я припускаю (будь ласка, виправте мене, якщо я помиляюся), що ви хочете повторно відобразити сторінку редагування, якщо редагування не вдається, і для цього ви використовуєте переспрямування.

Можливо, вам пощастить більше, просто повернувши подання знову, а не намагаючись перенаправити користувача, таким чином ви зможете використовувати 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-адресу із зворотним шляхом.

Це не буде працювати, оскільки ваша форма буде опублікована до дії контролера, яка не знатиме, як зберегти зміни. Спочатку потрібно опублікувати до дії збереження, а потім обробити переспрямування всередині неї.


Так, але він потрібен для перенаправлення назад на попередню сторінку, якщо редагування вдалося. Я думаю, що це не спрацювало, оскільки я використовував "id". Я змінив параметр на "url", як показано нижче, і, схоже, це спрацювало з моєї першої спроби, але мені потрібно перевірити його ще .... тримайся, і я опублікую те, що маю. Я вперше розміщую публікації на цьому сайті та приймаю тик, щоб звикнути.
Джейсон Енохс,

У цьому випадку ви можете розмістити попередню URL-адресу в ViewBag при початковому завантаженні сторінки редагування, а потім помістити її у приховане поле. Тоді ви можете отримати доступ до нього як частину вашого ViewModel в дії публікації та перенаправити на нього. Я вважав би за краще щось подібне, аніж надсилати через рядок запитів. Якщо ви хочете приклад, повідомте мене.
Гаррі Марсленд,

див., положення Гаррі, якщо (успіх). Тут ви можете перенаправити на будь-яку бажану сторінку. Назад на попередню сторінку. redirectToActionтакож може приймати параметри, контролер-дія-змінні.
IAmGroot,

Гаразд, Гері. Потримайте кілька хвилин. Я випробовую вашу техніку. Моя остання спроба, здається, працює, але ваша схожа більше на правильний спосіб зробити це ... Я роблю відразу три речі, тож це займе у мене пару хвилин.
Джейсон Енокс,

1
Я думаю, що тут є невелика помилка в коді. Замість використання: "return RedirectToAction (viewModel.PreviousUrl);" слід використовувати: "return Redirect (viewModel.PreviousUrl);"
AidanO

4

Для ASP.NET Core Ви можете використовувати атрибут asp-route- *:

<form asp-action="Login" asp-route-previous="@Model.ReturnUrl">

Приклад: Уявіть, що у вас є автомобільний контролер з діями

Індекс

Деталі

Редагувати

і ви можете редагувати будь-який транспортний засіб з Індексу або Деталі, тому, якщо ви натиснули редагувати з індексу, ви повинні повернутися до індексу після редагування, а якщо ви натиснули редагувати з деталей, ви повинні повернутися до деталей після редагування.

//In your viewmodel add the ReturnUrl Property
public class VehicleViewModel
{
     ..............
     ..............
     public string ReturnUrl {get;set;}
}



Details.cshtml
<a asp-action="Edit" asp-route-previous="Details" asp-route-id="@Model.CarId">Edit</a>

Index.cshtml
<a asp-action="Edit" asp-route-previous="Index" asp-route-id="@item.CarId">Edit</a>

Edit.cshtml
<form asp-action="Edit" asp-route-previous="@Model.ReturnUrl" class="form-horizontal">
        <div class="box-footer">
            <a asp-action="@Model.ReturnUrl" class="btn btn-default">Back to List</a>
            <button type="submit" value="Save" class="btn btn-warning pull-right">Save</button>
        </div>
    </form>

У вашому контролері:

// GET: Vehicle/Edit/5
    public ActionResult Edit(int id,string previous)
    {
            var model = this.UnitOfWork.CarsRepository.GetAllByCarId(id).FirstOrDefault();
            var viewModel = this.Mapper.Map<VehicleViewModel>(model);//if you using automapper
    //or by this code if you are not use automapper
    var viewModel = new VehicleViewModel();

    if (!string.IsNullOrWhiteSpace(previous)
                viewModel.ReturnUrl = previous;
            else
                viewModel.ReturnUrl = "Index";
            return View(viewModel);
        }



[HttpPost]
    public IActionResult Edit(VehicleViewModel model, string previous)
    {
            if (!string.IsNullOrWhiteSpace(previous))
                model.ReturnUrl = previous;
            else
                model.ReturnUrl = "Index";
            ............. 
            .............
            return RedirectToAction(model.ReturnUrl);
    }

2

Я знаю, що це дуже пізно, але, можливо, це допоможе комусь іншому.

Я використовую кнопку Скасувати, щоб повернутися до посилальної адреси. У поданні спробуйте додати це:

@{
  ViewBag.Title = "Page title";
  Layout = "~/Views/Shared/_Layout.cshtml";

  if (Request.UrlReferrer != null)
  {
    string returnURL = Request.UrlReferrer.ToString();
    ViewBag.ReturnURL = returnURL;
  }
}

Тоді ви можете встановити ваші кнопки href так:

<a href="@ViewBag.ReturnURL" class="btn btn-danger">Cancel</a>

Окрім цього, оновлення Джейсона Енокса чудово працює!


0

Ось лише ще один варіант, на який ви можете подати заявку на 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>

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


1
Я ще не пробував цього, але мені справді подобається, як це виглядає. Якщо це працює, тоді я думаю, що це краще, ніж приклад, який я розмістив кілька років тому. Я б спробував це зараз, але я заглиблений у Python на коробці Linux. Дякуємо, що поділились цим.
Джейсон Енокс,

Що станеться, якщо користувач відвідає веб-сторінку безпосередньо?
Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.