在 MVC 环境中处理返回 URL 的智能方法

发布于 2024-12-04 13:44:53 字数 693 浏览 0 评论 0原文

我一次又一次遇到的一个问题是,在用户运行某些操作(例如单击“返回...”链接或保存他们正在编辑的记录)后处理到上一页的重定向。

以前,每当我需要知道要返回哪个页面时,我都会向当前视图提供一个 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,因此如果可能的话,我希望获得与此相关的答案,但欢迎任何想法。

A problem I come up against again and again is handling redirection to the previous page after a user runs some action such as clicking a 'Back To ...' link or saving the record they are editing.

Previously whenever I have needed to know what page to return to, I would provide a returnURL parameter to my current view.

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

This isn't a very clean way of handling this situation, as sometimes the return URL contains parameters such as search strings, etc, which have to be included in the URL.

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

Also, this creates an issue when a user can go another page forward before coming back to the page with the returnURL because you have to pass the returnURL through all visited pages.

Simply calling the browser's Back functionality isn't really sufficient either, because you might want the page to refresh, e.g. to show the edits you just saved in the previous page.

So my question is, has anyone found a smart way to handle this kind of situation, specifically in an MVC environment?

Note: I am using ASP .NET MVC so if possible I'd like answers to pertain to that, however any ideas are welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

倦话 2024-12-11 13:44:53

设置 cookie 或使用会话变量有什么问题?您不这样做的唯一原因是,如果您无法控制调用您的页面,在这种情况下,您唯一的选择是查询字符串、发布值或引荐来源网址。

What's wrong with setting a cookie, or using a session variable? The only reason you wouldn't is if you don't control the page that calls into you, in which case your only options are query strings, post values, or referrer.

摇划花蜜的午后 2024-12-11 13:44:53

我想我可以将我的答案添加到这个问题中,看看其他人是否认为这是一个好主意。

我只是使用 TempViewData: 将其传递到控制器

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

,然后以与此类似的方式访问它(在我的真实版本中,我检查密钥是否在 TempData 中,并且 returnURL 是一个真实的 URL):

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

如果需要在第一个页面更改之后继续(即搜索页面 -> 编辑页面 -> 编辑部分页面),我将再次添加它

TempData["returnURL"] = TempData["returnURL"];

I thought I might add my answer to the question to see if others think it's a good idea.

I'm simply passing it through to the controller using TempViewData:

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

and then accessing it in a similar way to this (in my real version I check that the key is in TempData and that the returnURL is a real URL):

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

If it needs to continue on past the first page change (i.e. Search page -> Edit page -> Edit Section page) I'm adding it again

TempData["returnURL"] = TempData["returnURL"];
把时间冻结 2024-12-11 13:44:53

查看我的博客文章: 使用 cookie 进行控制在asp.net mvc 3上登录后返回页面

就像@Mystere Man提到的那样,您可以只使用cookie或会话。不久前我遇到类似的情况时,我就去买饼干了。

Check my blog post on it: Using cookies to control return page after login on asp.net mvc 3

Just like @Mystere Man mentioned, you can just use a cookie or session for it. I went for cookies back when I had a similar situation a while ago.

冰火雁神 2024-12-11 13:44:53

尝试注册一个 url 为 /{controller}/{action}/{id}/returnurl/{*url} 的新路由,然后在接受 url 作为参数的操作

Try register a new route of which the url is /{controller}/{action}/{id}/returnurl/{*url} and then use a RedirectToAction in the action that accepts url as a parameter

似最初 2024-12-11 13:44:53
Request.UrlReferrer.AbsoluteUri

尽管我仍然认为您不应该创建自己的“后退”按钮。

Request.UrlReferrer.AbsoluteUri

though i'd still argue that you shouldn't be creating your own "back" button.

并安 2024-12-11 13:44:53

使用拦截器或切面:

  1. 以某种方式拦截每个请求(例如,@Before 切面)并将请求的 URL 保存到会话中,每次都覆盖它
  2. 在视图层中,访问该 Session 对象根据需要,在您的情况下作为反向链接。

这种设计可以让您在需要使用时始终可以获取最新的请求。 这是一个示例 在 .NET 中编写切面/拦截器。另外,PostSharp 是一个 .NET 方面项目。

Use an interceptor or an aspect:

  1. Intercept each request in some fashion (e.g., a @Before aspect) and save the requested URL to the session, overwriting it each time
  2. In your view layer, access that Session object as needed, in your case for the back link.

This kind of design allows you to always have the most recent request available if you want to use it. Here's an example to write an aspect / interceptor in .NET. Additionaly, PostSharp is a .NET aspect project.

看轻我的陪伴 2024-12-11 13:44:53

目前,我还没有找到一种快速而肮脏的方法……所以我正在使用一种实用的方法。

在概念层面上,页面的“后退能力”应由您当前所在的页面决定。如果控制器中捕获的参数通过 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.
    }
}

视图(部分) // 没有双关语意图...或者也许是。 :)

您的 BarView 现在可以从其模型解释它需要返回的位置(使用 fooId)。

在 BarView 上(使用 MVC2 语法):

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

您也可以使用 Html.ActionLink。

或者:

您可以从 BaseViewModel 继承 ViewModel,它可以具有受保护的属性 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>

At present, a quick and dirty method has eluded me... so I'm using a practical method.

On a conceptual level, the 'back-ability' of a page should be determined by the page that you're currently on. The View can infer this (in most cases) if the parameters captured in the Controller are passed to it via the ViewModel.

Example:

Having visited Foo, I'm going to Bar to view some stuff, and the back button should return to Foo.

Controller

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.
    }
}

View (Partial) // No pun intended... or maybe it was. :)

Your BarView can now interpret from its model where it needs to go back to (using fooId).

On your BarView (using MVC2 syntax):

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

You can use Html.ActionLink as well.

Alternatively:

You can inherit your ViewModels from a BaseViewModel, which can have a protected property returnURL. Set this where necessary.

Example:

On your 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.
    }
}

On View:

<a href="<%=returnURL %>">Back</a>
最美的太阳 2024-12-11 13:44:53

通过在不离开页面的情况下显示的部分操作并使用 JQuery 制作对话框/向导工作流程可以更好地处理此问题吗?

然后您只需对对话框上的“完成”按钮做出反应即可刷新原始视图。

Would this be better handled by partial actions that display without leaving the page and using JQuery to make a dialog/wizard workflow?

Then you only need to react to the 'Finish' button on the dialog to refresh the original view.

绝影如岚 2024-12-11 13:44:53

对于您关于“保存他们正在编辑的记录”的问题,我认为重定向后获取(PGR)模式将适用于您。

如果您不熟悉它,这可能是阅读它的好地方。

For the part of your question regarding "saving the record they are editing" I would think the post-redirect-get (PGR) pattern would apply to you.

This might be a good place to read about it if you are not familiar with it.

在你怀里撒娇 2024-12-11 13:44:53
  1. 使用 Url.Encode(returnUrl) 对 returnUrl 进行编码以包含在 URL 中。
  2. 准备好重定向时,请使用 Url.Decode(returnUrl) 并使用实际重定向的值。
  1. Encode the returnUrl using Url.Encode(returnUrl) for inclusion in the URL.
  2. When ready to redirect, use Url.Decode(returnUrl) and use the value for the actual redirect.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文