1

Let me try to set the scenario here first. This is done using ASP.NET 4.0, MVC3, and C#.

I have a picture gallery. I have a manager for the albums in the picture gallery. Each gallery has a set of pages.

When I am using the manager for the albums, the view shows a list of current albums.

In the list of albums, there are choices to edit, delete, or manage pages in that album.

When selecting to manage the pages for the album, there is a list of pages, each with edit, delete, and view.

When the edit button for the page is selected, and edits are made then saved, my problem is encountered.

The button to get to the list of pages to manage from the list of albums sends the id via post to hide the albumid and other parameters.

So the view for the pages is generated from a [HttpPost] controller. Then, from the view to manage pages, when the edit button is clicked, the page for edit is generated from a [HttpPost] controller for the same reason (to hide parameters).

Here is the problem: Once the save button is clicked in the edit view, data is posted to a save changes controller via [HttpPost], but I do not want to return the edit view (refresh would repost changes and it is not really best practice). I want to return to the list of pages for the selected album. In doing this, I am using [HttpPost] from the edit controller to redirect back to the [HttpGet] controller for the view that lists the pages for the selected album. When I do this, the call looks like this:

return RedirectToAction("ManagePages", new { albumId = model.AlbumId });

This unfortunately makes the url have the album id shown: http://XXX/ManagePages?AlbumId=56.

How can I return to the ManagePages view for the same selected album without showing the album id in the parameter list?

Travis J
  • 81,153
  • 41
  • 202
  • 273

3 Answers3

1

You could store the album id in the TempData just before performing the redirect using:

TempData["AlbumId"] = model.AlbumId;
return RedirectToAction("ManagePages");

Then in the ManagePages GET action you could read the contents of the id:

int albumId = (int)TempData["AlbumId"];

Note: Once the id has been read the contents of TempData["AlbumId"] will be cleared.


Update:

Actually, if you use TempData and the user clicks refresh then the data will be lost on the refresh. Therefore, you could instead use the Session:

Session["AlbumId"] = model.AlbumId;
...
int albumId = (int)Session["AlbumId"];
Dangerous
  • 4,818
  • 3
  • 33
  • 48
  • 1
    Also, if the user refreshes on the page that has just received this TempData, will the page fail since it is expecting to have data which was not sent after rendering? – Travis J Dec 11 '11 at 23:04
  • 1
    I have updated my answer to also use the Session. The TempData is actually probably best for passing things like error messages where it does not matter if they are lost on refresh. However, I myself would consider passing the id to the URL as part of RedirectToAction(). It isn't that bad to expose to the id to the user as long as you are aware (and perform any required server side checking) as a hacker could potentially change this to a different id (valid or invalid). – Dangerous Dec 12 '11 at 07:59
  • a) Is changing the id all a malicious user could do? b) On httpget could I just reassign the tempdata and have it held until it needs to be read again or is that considered bad practice – Travis J Dec 12 '11 at 08:59
  • a) A malicious user could potentially change any value passed in the url or that is hidden in a form. If you expose an id such as an album id you should be fine. Many online shopping websites use product or category ids in the url. If you change and submit them you will get an incorrect product or category (the users fault for changing) or an error page, either way no harm done. As long as you don't expose sensitive information on the client you should be fine. See 'Task3 - Adding an Id parameter embededed in the url' of the following link: http://msdn.microsoft.com/en-us/gg592076 – Dangerous Dec 12 '11 at 09:48
  • b) Whilst possible to reassign to the TempData or to use .Peek() to not remove the contents, if you are going to do this I would have thought it best to use the session. – Dangerous Dec 12 '11 at 09:49
  • Thank you for your suggestions and replies, they are very appreciated. Just to be thorough, and make sure I have this correct: It is okay to expose ids in the URL? It is not bad practice to expose ids in the URL? (As long as bad ids and un-authorized ids are handled) – Travis J Dec 12 '11 at 20:05
  • 1
    http://stackoverflow.com/questions/910683/why-is-id-in-the-url-a-bad-idea http://stackoverflow.com/questions/3629134/should-i-expose-a-user-id-to-public Default route supplied with MVC3: new { controller = "Home", action = "Index", id = "" } It should be fine for you to supply a url with an id as long as you do not expose sensitive information and as long as you guard against the possiblity that the id could be a different value than you expect. But its the users fault for changing if you return an error page. – Dangerous Dec 12 '11 at 22:46
0

Before doing the RedirectToAction, you can set a cookie with the album ID. Then you read it in the ManagePages action.

However, it is worth stating that if you are sensitive about internal IDs being known externally, your application still exposes them via the HTML source. Other users could use them to view data they are not suppose to unless you have some sort of authentication mechanism in place.

jmacinnes
  • 1,589
  • 1
  • 11
  • 21
0

You could hide the ID in a TempData variable. TempData persists through one redirect.

hawkke
  • 4,242
  • 1
  • 27
  • 23