Умный способ обрабатывать возврат URL в среде MVC - PullRequest
15 голосов
/ 12 сентября 2011

Проблема, с которой я сталкиваюсь снова и снова, заключается в обработке перенаправления на предыдущую страницу после того, как пользователь выполняет какое-либо действие, такое как нажатие на ссылку «Вернуться к ...» или сохранение записи, которую он редактирует.

Раньше всякий раз, когда мне нужно было узнать, на какую страницу вернуться, я предоставлял параметр returnURL для моего текущего представления.

http://blah.com/account/edit/1?returnURL="account/index"

Это не очень чистый способ справиться с этой ситуацией, поскольку иногда возвращаемый URL-адрес содержит такие параметры, как строки поиска и т. Д., Которые необходимо включить в URL-адрес.

http://blah.com/account/edit/1?returnURL="account/index?search="searchTerm""

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

Простовызова функции «Назад» браузера тоже не достаточно, потому что вы можете захотеть обновить страницу, например, чтобы показать изменения, которые вы только что сохранили на предыдущей странице.

Так что мой вопрос: нашел ли кто-нибудь умныйспособ справиться с такой ситуацией, особенно в среде MVC?

Примечание : я использую ASP .NET MVC, поэтому, если возможно, я хотел бы получить ответы на этот вопросОднако любые идеи приветствуются.

Ответы [ 10 ]

12 голосов
/ 15 сентября 2011

Что не так с установкой файла cookie или использованием переменной сеанса? Единственная причина, по которой вы этого не сделаете, заключается в том, что вы не контролируете страницу, которая вызывает вас, и в этом случае вашими единственными опциями являются строки запроса, значения post или реферер.

3 голосов
/ 15 сентября 2011

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

Я просто передаю его в контроллер с помощью TempViewData:

@{
   TempData["returnURL"] = Request.Url.AbsoluteUri;
}

и затем доступ к нему аналогично этому (в моей реальной версии я проверяю, что ключ находится в TempData и что returnURL является реальным URL):

return Redirect(TempData["returnURL"].ToString());

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

TempData["returnURL"] = TempData["returnURL"];
2 голосов
/ 19 сентября 2011

Проверьте мой пост в этом блоге: Использование файлов cookie для управления страницей возврата после входа в систему на asp.net mvc 3

Так же, как упомянуто @Mystere Man, вы можете просто использовать файл cookie илисессия для него.Я пошел за печеньем назад, когда у меня была похожая ситуация.

1 голос
/ 21 сентября 2011

Что касается части вашего вопроса, касающейся «сохранения записи, которую они редактируют», я бы подумал, что шаблон post-redirect-get (PGR) будет применяться к вам.

Это может быть хорошим местом, чтобы прочитать об этом, если вы не знакомы с ним.

1 голос
/ 19 сентября 2011

Будет ли это лучше обрабатывать частичными действиями, которые отображаются, не покидая страницу, и используя JQuery для создания диалогового / мастера рабочего процесса?

Тогда вам нужно только отреагировать на кнопку «Готово» в диалоговом окне, чтобыобновить исходный вид.

1 голос
/ 15 сентября 2011

В настоящее время быстрый и грязный метод ускользает от меня ... поэтому я использую практический метод.

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

Пример:

Посетив Foo, я собираюсь Bar, чтобы просмотреть некоторые вещи, и кнопка возврата должна вернуться к Foo.

Контроллер

public ActionResult Foo(string fooId) // using a string for your Id, good idea; Encryption, even better.
{
    FooModel model = new FooModel() { fooId = fooId }; // property is passed to the Model - important.
    model.Fill();
    return View("FooView", model);
}

public ActionResult Bar(string fooId, string barId)
{
    BarModel model = new BarModel() { fooId = fooId; barId = barId };
    model.Fill()
    return View("BarView", model)
}

ViewModels

public class FooModel
{
    public string fooId { get; set; }

    public void Fill()
    {
        // Get info from Repository.
    }
}

public class BarModel
{
    public string fooId { get; set; }
    public string barId { get; set; }

    public void Fill()
    {
        // Get info from Repository.
    }
}

Просмотр (частичный) // No pun intended... or maybe it was. :)

Ваш BarView теперь может интерпретировать свою модель там, где ему необходимовернуться к (используя fooId).

На вашем BarView (используя синтаксис MVC2):

<a href="<%= string.Format("/Foo?fooId={0}", Model.fooId) %>">Back</a>

Вы также можете использовать Html.ActionLink.

В качестве альтернативы:

Вы можете наследовать ваши ViewModel от BaseViewModel, которая может иметь защищенное свойство returnURL.Установите это там, где необходимо.

Пример:

На вашей ViewModel:

public class BarModel : BaseViewModel
{
    public string fooId { get; set; }
    public string barId { get; set; }

    public void Fill()
    {
        returnURL = string.Format("/Foo?fooId={0}", fooId)
        // Get info from Repository.
    }
}

При просмотре:

<a href="<%=returnURL %>">Back</a>
1 голос
/ 15 сентября 2011

Используйте перехватчик или аспект:

  1. Перехватывает каждый запрос некоторым образом (например, аспект @Before) и сохраняет запрошенный URL в сеансе, перезаписывая его каждый раз
  2. В вашем слое представления, при необходимости, получите доступ к этому объекту Session для обратной ссылки.

Этот тип дизайна позволяет вам всегда иметь самый последний доступный запрос, если вы хотите его использовать. Вот пример для записи аспекта / перехватчика в .NET. Кроме того, PostSharp - это проект аспекта .NET.

1 голос
/ 12 сентября 2011
Request.UrlReferrer.AbsoluteUri

хотя я бы все еще утверждал, что вам не следует создавать свою собственную кнопку "назад".

1 голос
/ 12 сентября 2011

Попробуйте зарегистрировать новый маршрут с URL-адресом /{controller}/{action}/{id}/returnurl/{*url}, а затем используйте RedirectToAction в действии, которое принимает url в качестве параметра

0 голосов
/ 21 сентября 2011
  1. Кодируйте returnUrl, используя Url.Encode(returnUrl) для включения в URL.
  2. Когда будете готовы к перенаправлению, используйте Url.Decode(returnUrl) и используйте значение для фактического перенаправления.
...