A smart way to handle Return URLs in an MVC enviro

2020-07-02 11:28发布

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.

10条回答
姐就是有狂的资本
2楼-- · 2020-07-02 11:56

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>
查看更多
可以哭但决不认输i
3楼-- · 2020-07-02 11:58

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.

查看更多
Anthone
4楼-- · 2020-07-02 12:02

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.

查看更多
Melony?
5楼-- · 2020-07-02 12:10
Request.UrlReferrer.AbsoluteUri

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

查看更多
登录 后发表回答