I have a ActionLink, that calls my public ActionResult, and I would like it to return back to the page that it was called from, but how?
There are a couple of tricks that you can use for this.
The simplest is ...
return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
AbsoluteUri may not give you the exact path you are looking for, but UrlReferrer should have the imformation you are looking for. Redirect returns a subclass of ActionResult so it is a valid return value.
Another idea is to base the redirect location off of stored values. This is useful when you are going to make multiple requests before you want to redirect, such as when you validate a form and show validation issues on the first response. Another situation will be when the referrer is not a local site. In either case, your referrer won't be what you want it to and you will need to retrieve the correct location from somewhere else.
Specific implementations include using a hidden input field on your form, session state, pulling a descriminator value from your route data, or even just a more constant value like HttpContext.Request.ApplicationPath.
Good luck.
Keep in mind that due to the state-less nature of the web, your ActionResult isn't "called from" your ActionLink as much it is simply a url that the user-agent requested.
Because of this, the only real "built-in" way you can know where that user was coming from is by inspecting the http Request headers to see what the referring page was:
string referrer = Request.Headers["referer"];
You'd then be responsible for parsing out the Action method from this url, if you were going to call it directly. Be aware that this referrer may not be a link within your own site.
Related
I have a hidden field in the layout page
#Html.Hidden("idmember", "123456");
I want to access this value in my controller's action
public ActionResult Index(string idmember){
//value for test parameter is null
}
When I do viewsouce on the page - the value is there.
What is the right way to access the value from layout page? Thanks,
UPDATED. based on the help from others, I released in order to pass value to the action I need to do a form post (and it works) but I have an actionlink
example:
#Html.ActionLink("View Member", "index", "member",new{idmember="12345"}, null)
This does work and my URL is /member/index?idmember=12345 But I wanted to make the link cleaner instead of passing the value in the querystring I wanted to somehow pass the value as hidden field? or another way to the action? Is it possible?
Regarding your edit: you shouldn't want to. You pass parameters either in the URL or as request body variables (e.g. POST body).
You can circumvent this for example by using the session to store the ID, but this is going to cause unexpected behavior and will break your web application. Session timeouts, users using multiple tabs and users wanting to share links are going to cause problems.
In short: use the URL for what it's meant to do; don't care about arbitrary "cleanliness".
If I have 2 controller actions:
[HttpGet]
public ActionResult Login()
{
//...
return View();
}
and
[HttpPost]
public ActionResult Login(FormCollection values)
{
//...
return RedirectToAction("Index","Home");
}
It seems that the Post decoration is required for this to work (which makes sense), but the HttpGet decoration is entirely optional. It works fine with or without. It seems that MVC defaults controller actions to HttpGet unless otherwise specified.
I'll have to decided if I want a future reader of my code to have to figure that out on my own or not, or whether I want to have to remember to add HttpGet everywhere for consistency. But my question is not about whether it is a good practice to include the explicit decoration even though it is defaulted that way already.
My question is: is it ALWAYS the case that I don't need to decorate controller methods with HttpGet? Is there some way that this can bite me if I do or do not explicitly specify? I've searched on this a but and all I can find is posts describing why you might want to use both annotations rather than the reason for/against including the HttpGet specifically.
You don't have to specify this explicitly, no. However, please note:
Not specifying the verb on an action will mean that the method accepts both GET and POST. If there are two actions, however, the one labelled POST will be used for POST and the other will default for GETs.
Applying HttpGet will mean an action accepts only GET requests.
Labelling actions as GET can make it more obvious to other developers what your intention is.
Is there some way that this can bite me if I do or do not explicitly specify?
Not very likely. I could imagine a situation where something might be showing some strange behaviour or not working as expected because of it, but it'd be rare.
Is there some way that this can bite me if I do or do not explicitly specify?
Here I want to develop an answer of Rowan Freeman about the consequences of not using [HttpGet] explicitly for every GET method.
As it was already mentioned, a method without [HttpGet] annotation will accept both GET and POST request (unless there is another method with same name that is annotated with [HttpPost]). If a method is explicitly annotated with [HttpGet], 405 Method Not Allowed will be returned.
One consequence that I could imagine is that if an attacker wanted to send big amount of data through GET request, it would have a limit. Without [HttpGet] annotation, this limit is not a problem, because an attacker can switch to POST and do the same without any limit.
Another similar case is that:
HTTPGet can carry only string data whereas HTTPPost can carry both string and binary data.
Yet another thing is that POST requests will probably not entirely be logged on a server, therefore an attacker can somehow hide it's activity from an administrator as attackers payloads won't be visible (body won't be present in logs).
A comparison between POST and GET (which I cited from) can be found here:
ASP.NET MVC 5 – HTTPGET And HTTPPOST Method With Example
Of course, all of these cases are pretty rare, but this is what exploiting is about - finding rare things that can turn out to be a vulnerability.
To conclude, it is a good habit to always write [HttpGet] annotation in controller methods. It is just a one line that can improve security of your web application.
As I am new to ASP.NET MVC can anybody tell me the difference between return RedirectToAction() and return View()?
return View() tells MVC to generate HTML to be displayed and sends it to the browser.
RedirectToAction() tells ASP.NET MVC to respond with a Browser redirect to a different action instead of rendering HTML. The browser will receive the redirect notification and make another request for the new action.
An example ...
let's say you are building a form to collect and save data, your URL looks like SomeEntity/Edit/23. In the Edit action you will do return View() to render a form with input fields to collect the data.
For this example let's say that on successful save of the data you want to display the data that has been saved. After processing the user's submitted data, if you do something like a RedirectToAction("Index") where Index is the action that will display the data. The browser will get a HTTP 302 (temporary redirect) to go to /SomeEntity/Index/23.
Return View doesn't make a new requests, it just renders the view
without changing URLs in the browser's address bar.
Return RedirectToAction makes a new request and the URL in the browser's
address bar is updated with the generated URL by MVC.
Return Redirect also makes a new request and the URL in the browser's address
bar is updated, but you have to specify the full URL.
RedirectToRoute redirects to the specified route defined in the the
route table.
Between RedirectToAction and Redirect, best practice is to use
RedirectToAction for anything dealing with your application
actions/controllers. If you use Redirect and provide the URL, you'll
need to modify those URLs manually when you change the route table.
As an addition to all answers above, if you are using Implementing Validation using Data Annotation, use return View() instead of RedirectToAction().
Validation message will not work using RedirectToAction as it doesn't get the model that is not valid and your validation message will not show as well on your view.
here is simplest explanation of rendering view in mvc.
Another opinion question:
What is the proper (in your opinion) to check for nulls in an MVC controller. For instance, if you have an edit controller that fetches a record from the db based on an id, what do you do if that record is not found? I found this article, but I'm not sure I like that method. Do you just check for it with an if statement and redirect to a 404 page? What solution do you use?
I don't know if it's best practice, but I check with an if and redirect to a "NotFound" view that states "The company/client/whatever you requested does not exist or was deleted."
Did it this way simply b/c I followed the NerdDinner tutorial when setting up the skeleton of my site, and that's how they do it.
That's what I do in my blog:
public ActionResult DisplayPublication (int nr)
{
if (!PublicationExists (nr))
throw new (HttpException (404, ""));
// ....
return ...;
}
As a general rule of a thumb, if a resource is requested which does not in fact exist, return HTTP 404. Definitely not return 200 OK along with the message about the missing resource. If not found, should be 404. If you changed the structure of your urls, consider 301 Moved Permanently.
Depending on the type and logic of the software you're developing, you may decide to exercise a different reaction to that situation, it's up to you.
I use a method similar to the article you linked to: an action filter that returns a 404 if the view model is null. I've combined it with a custom action invoker (like this) so that I don't have to put the filter attribute on everything.
Since I mentioned it, there are several other types of actions you can do if you go the action filter route. I have/had filters that will:
Automatically redirect to the Index view after a successful edit.
Redirect to the same page if the ModelState is invalid.
Redirect to an access denied page if a security exception is thrown.
I'm thinking about refactoring these to a convention registry so I can have something like:
When.ModelIsNull.RedirectTo<SharedController>(c => c.NotFound());
For("Edit").ModelStateIsInvalid.Redisplay();
For("Edit").OnSuccess.RedirectTo("Index");
On<SecurityException>().RedirectTo<SharedController>(c => c.AccessDenied());
Then if I wanted to change how a particular behavior works I just change it in one place. For example, instead of going to Index, I could redirect to the View view.
For("Edit").OnSuccess.RedirectTo("View");
I hope this gives you some ideas.
Edit: Here is how to could accomplish something similar using FubuMVC (which I love to steal ideas from)
I have the following scenario:
I have an edit page, which can be called from different pages. These pages could be the detail view for the current entity, or the list view for the entities (with or without a search in the route).
HOW do I cleanly redirect to the original calling page using the MVC framework? Of course I could simply pass the HttpContext.Request.Url value by holding it in my TempData, but that sort of smells, in my eyes (or, err, nose). It's on a lower level than the rest of the code.
Is there a way to get the routevalues for the previous page in a controller context? If I have that, I could store that temporarily and pass that to the redirect.
Do not use TempData when not redirecting. One AJAX request from your edit page, and the TempData will go away.
Tomas is right that a hidden element or query string parameter is the way to go. But make sure you sanitize the value submitted. You don't want to redirect any old site on the web; you need to ensure that the page to which you redirect is part of your sites.
you can always have a hidden form element telling the controller where to redirect when posting a form. when using a get request, you could use a querystring in a similar way. it might not be the most beautiful solution, but it's quite a lot safer than trusting httpreferrer or other headers that could easily be changed (or ommitted) by the browser.