Determining the previous page in mvc 3 - asp.net-mvc

How to check the previous page in mvc 3 application.
Previous Page.
On click of the above link I have to go back to previous page.
How to do this ?

This will depend on how is the navigation organized on your website. One possibility is to use the history.go(-1) javascript function which will simply simulate the browser back button:
Previous Page.
Another possibility is to have the calling page pass a ReturnUrl query string parameter to this page which could be used to construct the link:
Previous Page.
Of course this assumes that when you called the controller action that rendered this view you have passed the ReturnUrl query string parameter.

Same as Matthew's answer but using a session variable. That way you could update it selectively in the Action you want. For example, on a POST action you wouldn't want them to go back to that view with form values there. What you really want is for them to go back to the page before that.
public ActionResult MyNextPage(string prevUrl)
{
Session["prevUrl "] = prevUrl;
View();
}
Then in the View:
Previous Page
Note that if session is expired or null it will throw an exception.

Related

ASP.NET MVC controller action restricted to a specific view

Is there a way to restrict a controller action to be accessible only from a specific view? I have a Details page for a queried entity in my database and basically by a button and a simple JS confirmation prompt I would like to change few properties of this object and save it back to the database. I've developed a controller action method which does the job but I have no idea how to restrict access to it, so users cannot (un)intentionally modify entities by passing a specific url in the browser. I would like the action to be only accessible on this specific Details page, by pressing the designated button.
I tried using [ChildActionOnly] but it's only accessible from another action method, and not a view.
Thank you for your help.
Thanks to Stephen Muecke's comment I've managed to get it working.
The button is a simple Action Link, which redirects to the restricted controller action:
public ActionResult ReturnBook(int id)
{
if (Request.UrlReferrer == null)
{
return HttpNotFound();
}
//code
}
The method checks, if there is any UrlReferrer at all. Typing action url in the browser results in the referrer being null.
If the call is made by ActionLink from a View, the UrlReferrer is not null and optionally its property Request.UrlReferrer.AbsolutePath can be checked and compared to a desired url, from which the invoke can only be made. In my case, as I am not invoking this method anywhere else in my code, I stayed with just null/notnull condition.

New to MVC, am I the only one getting screwed by this common scenario

Heres the scenario - using asp.net MVC with jquery mobile - newbie on both
Problem: Back button sends a GET to a page that was created with a POST
Scenario:
Page 1 has a searchbox and submit button - clck submit does POST to page 2.
Page 2 has list of serch result links, click a search result, go to page 3
Click back button on page 3, and it sends a GET to page 2.
Tried on Safari and Firefox. Firebug showing a GET on the back button.
Is this common? How would you deal with this?
A) When submitting form, somehow add the textbox to the URL (sounds tricky)
B) Mark the search page action with both HTTPPost and HTTPGet? Then save the search text in a session or somewhere?
C) Is there a better option?
Any advice appreciated!
I think may have approached this the wrong way. In general, POST should be used for requests that potentially modify state (update database etc) on the server, and GET should be used for read-only operations.
In this case it is a read only action therefore a HTTP Get is the correct http verb to use. Assuming you are using Razor your form action would look like
#using(Html.BeginForm("Index", "Search", FormMethod.Get))
//generates an url like /search?q=searchterm
It sounds like you want page 1 and page 2 to have the same url and essentially 'post-back' to the first page, such that if you go backwards you get back to the first original non-posted page.
You can achieve this by using the [HttpPost] and [HttpGet] attributes
In your Controller you can have this
[HttpGet]
public ActionResult Search()
{
//action result get code
}
[HttpPost]
public ActionResult Search()
{
//your result post code here
}

ASP.NET MVC 2 Returning to previous screen

Is there a way to return to the previous view without having to record all the parameters that were used to get to the view in question. Consider this situation. You have a search screen with input parameters, you press search and get results displayed on the page. You click on one item to get a detailed look which redirects you to a new view. Does MVC have the ability to get the previous query string that contains the search parameters?
Not that I know of. You could save it in the session, but how about using JS history.back()
Wouldn't the user just use the back button on the browser? Are you wanting to present a "Back to results" link on the detail page? Also look at Request.UrlReferrer if you don't want to save the search parameters in session or a cookie.
You can use Request.UrlReferrer

Is it i possible to prevent certain PartialViews from being served if requested directly?

I'm working on a site that has routes to actions which render Partial Views. A lot of these partial views are components which together make up a complete page.
For instance on a search page I'm working on has a text box, a list of tabs, and a Table.
Seach of these can be accessed with a URL similar to
/Search/SearchPanel
/Search/Tabs/{SearchTerm}
/Search/ResultsTable/SearchTerm?tab=[currently selected tab]
and these are all rendered on with a RenderPartial on my Index page.
When the page loads, it will display each of these components the way I want it. But at the moment there's nothing stopping a user from going directly to the url
/Search/Tabs
to render only a tab control which is meaningless outside the context of the rest of the elements on the page.
Is there a way for me to prevent this?
Have you tried marking your Controller method as private?
private PartialViewResult MyPartialResultMethod()
This should allow you to call it from within your code to build up your pages and disallow any public access such as through a URl.
I'm testing this now to make doubly sure my answer is correct so I'll update as I test.
In your tabs example you could simply restrict access by using a second controller method for Tabs that's private.
So you'd have something that looks like:
public ActionResult Tabs(string searchTerm) // When a search term is passed.
and
private ActionResult Tabs() // When no search term is passed.
You could create an ActionFilter which checks if the Request.IsAjaxRequest() is true. If it's not (meaning the user is calling the view directly), re-direct accordingly.

How do I specify a return url for a link to the login form?

Simple enough, it would seem, but it turns out not to be - mainly due to the fact that the View can't possibly know which way through Model and Controller you got there. Regardless, it is a problem that needs a solution:
I have a login link, that takes the user to a form to enter username and password. When the user clicks "submit", I want to redirect to the page he was viewing. The easiest way to do so seems to be specifying the url to the current page as a querystring (...?returnUrl=...) and everything else is already built.
But where do I find this url from my view, when rendering the link? I naturally can't use a RedirectToActionResult as I don't want to actually transfer the user - only render the url in a link. How to?
EDIT:
I have now started a bounty on this question, and therefore I see fit to clarify my needs as well.
I have a UserControl named Login.ascx in my Shared folder. In it, I render an ActionLink to the login form, and it is included in the footer on my Masterpage. What I want to accomplish is the following:
When the ActionLink is rendered, the querystring returnUrl is appended with the a route to the view that is currently being rendered. If this is accomplished, the user will be taken back to the page he/she was viewing after successful login with functionality that is already build into the ASP.NET MVC Framework.
The reason the previous answers have not been sufficient is mainly that they have not provided a way to build the route url to the current view. I do know how to append a querystring, but I do not know how to find out what to put in that string.
In order to mark an answer as the answer, I want a method to re-construct the route to the currently shown view, from a usercontrol in the masterpage.
The solution is to use HttpContext.Current.Request.RawUrl like this:
<%= Html.ActionLink("log on", "LogIn", new { controller = "User", returnUrl = HttpContext.Current.Request.RawUrl }) %>
Or with an extension method from MVC futures (Microsoft.Web.Mvc.dll):
<%= Html.ActionLink<AccountController>(c => c.LogOn("name", "password", false, HttpContext.Current.Request.RawUrl), "login here")%>
ActionController is the default one in mvc but just add returnUrl to your own.
One way would be to build the links that send the user to the login form, with returnUrl=/PageToReturnTo (Login for example). You'd want to write it so the return url was constructed from your routes though, manually writing those links on every page could be cumbersome.
The default login action in MVC has the returnUrl functionality already built. Just need to pass it a value and it will do the rest. Here's a copy'n paste of the method signature from a fresh project.
public ActionResult Login(string username, string password, bool rememberMe, string returnUrl)
Hope that helps ya!
You can use Page.Request.Url to get the route that resulted in the currently rendered view.
Though that's more of a cosmetic detail, you might want to unify the requests that came through the '/' and '/default.aspx' routes and always return to the '/' route. I have a helper property in my master page that does exactly that.
protected Uri RouteUrl
{
get
{
if (Page.Request.Url.AbsolutePath.StartsWith("/default.aspx", StringComparison.OrdinalIgnoreCase))
{
return new Uri(Request.Url, new Uri(Response.ApplyAppPathModifier("~/")));
}
return Page.Request.Url;
}
}
I don't know about ASPX, but there are a couple of problems we encountered building this:
When the user gets their password wrong, and loops-round the Login page to have another go, the Target must still be preserved.
We also decided to preserve POST variables to a page that then required the just-in-time login

Resources