Heading
I want to pass some variables from one page to another but I don't want them to appear in the URL. When I use a form to post the an ActionResult it works fine. However, when I do this
return RedirectToAction("Trackers",new{page = 1, orderby=desc});
I get the URL:
http://examplesite.com/Trackers?page=1&orderby=desc
Is there any way I can get the following URL instead but still pass the page and orderby variables "behind the scenes"?
http://examplesite.com/Trackers
Thanks
TheLorax
I'm not sure it's a good idea to do what you're suggesting, however, you might be able to use the TempData (same place as the ViewData) to save your information before the redirect. I believe that after your next request, anything in the temp data is cleared out.
You could pass a Model object containing the page number and the orderby instead of an anonymous object, and have your view inherit the model class of the object you are passing. Your model object with the page number and orderby then becomes available to the view, without employing a query string
This is not, however, the preferred method of doing this. Your model objects should be reserved for their intended purpose, which is passing actual data to your view.
When you use RedirectToAction method the browser will recieve an http redirect response from the server and then will do a GET request to the new URL.
I think there is no way to make the browser make a POST request when redirecting.
Also it is better to pass these variables through the query string in order for the user to be able to bookmark the page.
Related
I am having an issue with my session variables. I am adding objects to session, so that when i navigate to the next page (building a sort of questionnaire) i can retrieve these values in another Controller action, and use the stored value to make some calculations.
It is also said that this functionality is used for the user to go backwards through the questionnaire, should they wish to change an input to get a different outcome. However upon going backwards, the variables are gone, and my controller action code fails and brings back a null reference exception.
Any thoughts on why this is doing this? I am adding the the variable to session using following way:
Session["UserInfo"] = myObject;
and retrieving like so
InputData data = (InputData) Session["UserInfo"];
any reasons why i'm losing these objects. If i go back and click submit again , they're back in session and usable on the following page. I don't think this is a session timeout issue as i do it well within 20mins, usually like 30secs (as i'm developing the system and testing and making changes etc.)
I have solved this, my issue was the GET and POST requests on my action controllers. I was not specifying two controller actions explicitly (HTTPGET and HTTPPOST) so all requests going to the same action, and therefore was over-riding the session variable with NULL as nothing was being posted, as a ajax get request.
Setup up two action results HTTP POST and HTTP GET one with input parameters and the other without. Never crossed my mind, until had a cup of coffee and a fresh brain.
I've some code like the following;
We're going to create a Note but we may know the CustomerId when we do so I've two URLs;
public ActionResult CreateByCustomer(int id)
{
Session["ncAppointmentId"] = 0;
Session["ncNoteDate"] = null;
SetConsultant(0);
return RedirectToAction("Create", "Note", new { id = id });
}
public ActionResult Create(int id = 0)
{
int _CustomerId = id == 0 ? Convert.ToInt32(Session["CustomerId"]) : id;
Session["TemplateIds"] = null;
and so on.......
ViewBag.CustomerId = _CustomerId;
When I look at the performance in Firebug the RedirectToAction causes a GET with a '302 Found' status which can incur up to 1 second's delay.
If I change the RedirectToAction line to
return Create(0);
Then the GET doesn't happen and performance is improved.
But I'm looking for opinions on what the downside is or what I've missed ?
The RedirectToAction result tells the client to request a new page, so it will naturally incur overheads since the client is now having to make a second request to your server. Sometimes this is necessary, sometimes - as in your example - not.
Generally I use RedirectToAction to return the client to a specific page after performing an action such as creating a note. This can be useful if you're on a page that lists notes and you want to refresh the page after creating a new one. The end result is that the page is refreshed, and the Create action does not appear in the user's browser history.
If your Create method returns a View, there can be some interesting side effects of calling it directly. In general the MVC code will handle it, but you can get some weird results - like the client's URL being different to what you expect in the subsequent requests, etc. If you're OK with this, fine.
Another option would be to get rid of the CreateByCustomer action and simply call the Create view with a parameter - named customerID for instance. This gives you the same ability to call it different ways without having to have multiple entry points. The client's location would reflect (in the query string) the difference between Create and Create?customerId=12345 which may or may not be what you're after.
<opinion>
Some Style Notes:
If you're storing lots of session data, create a class to hold it instead of creating lots of entries in Session[].
It's not particularly difficult to use jQueryUI to create an in-page editor for your notes rather than defining a view - check out this example. More elegant too :P
</opinion>
The RedirectToAction method is going to return an HTTP response that has a Found status code and a Location URL pointing to the place you are redirecting the client. The cost is simply another GET request, which I would not consider expensive. The decision to redirect or not should be made based on whether it conceptually makes sense, not based on whether you are making one less GET request.
I don't entirely understand the motivation here, however. If you elaborate on why you are trying to redirect, maybe I can help you choose a pattern that makes more sense.
Typically, you would not name a method Create* in an HTTP API. The idiomatic, correct prefix is Post* or Put*, depending on whether you are adding a new resource (but naming it) or creating/replacing a resource (and naming it), respectively.
The big difference is regarding if you want the url to change to the "Create" one. If it's ok to show whatever you are showing with that url, then avoid the redirect. Redirect is useful when you have an old url and you want it to point to a new one and also in the situation when you want to avoid saving new stuff if the user refresh de page (as it will refresh only the redirect request and not the post).
Unfortunately because of the wide use of the word "hashtag" and "httprequest" i couldn't find any search results that gave me an answer on whether something like this is even possible.
If i have a url like this:
/Orders/Product#12345
The HttpRequest class shows me that the FilePath, RawUrl, and all other members that show the url as
/Orders/Product
It just gets rid of the hashtag, and i can't find a place to view it.
Is there any way for me to be able to see what hashtag is at the end of the URL from the codebehind? I know i could easily make this a QueryString parameter, but i like the way this looks better, so if there's a way to do it, i'd like to find out what it is :)
Thanks in advance!
It just gets rid of the hashtag, and i can't find a place to view it.
That's because it doesn't get sent to the server. It's not part of the request - it's only relevant on the client side. If you need to do anything clever with it, you'll need to write some Javascript to access it.
Browser is not required to do GET request in case of navigation to bookmarks on the same page (what #12345 is). So you may reconsider using it for normal requests.
As others have stated this value is not sent to the server. While it's possible to send the value to the server using JavaScript, in this instance you should make it a query string parameter.
If you are using it in a view:
Typeahead
This is the code I currently use:
<% Uri MyUrl = Request.UrlReferrer;
if( MyUrl != null)
Response.Write("Back"); %>
I would think there is a more "MVC Html helper" way to do a "Back" button. This may require more information about the routes already setup, a list of possible parameters, etc. but I don't want to assume this is the case. Maybe there is some way to match the url to the defined routes like in the manner a regular expression works?
What about adding the data you want to TempData, in an actionfilter or base controller class).
Each time when a page executes, it will add its info to the TempData, and the next page will know what the referrer was.The back button itself will be an HtmlHelper, that will simply go and fetch the data from the TempData.
This way you also eliminate the problem that some users don't send referrer info in the request.
well, for one you could always do what you did above, but inside a HtmlHelper.
As you pointed out, there's really too many variables to doing it based on routing, unless you havea known workflow (e.g. for a wizard).
I would suggest making it part of the view model, populated in your action. You could continue to use the referrer to populate it, or you could even have a "back url" parameter on your action, so that the calling page could supply its own back url.
does it reload the entire page or does it have the intelligence to only send the necessary js to update the needed parts of the page that have changed?
if it does the latter that would be a god send, however im probably being dreamful. it probably returns the entire view without any regard, right?
edit: answer seems to be no, everything is returned.
edit added:
do you think it would be difficult to write a framework where mvc compares last html it output to the current html we want to output, and instead of sending the entire html, figure out what has changed and generate js code that will do the updating as compared to previous html? (presuming nothing was manually changed on the client using js)... maybe an idea for a codeplex project? or maybe something like this exists?
Well, it entirely depends on how you do it.
You can return anything you want, when using ajax its common to return your data in JSON. Example:
public ActionResult GetCustomers()
{
if(Request.IsAjaxRequest)
return Json(db.GetCustomers());
return View(db.GetCustomers());
}
This will return all customers Json encoded if the request was made using Ajax.
You can stil return anything you want, if you want to return a view, it's just to
return View(model);
If you dont want to return the layout (master page), just return the MasterPageFile directive from your view.
And no, it does not reload the entire page, that's why it's called Ajax.
Frankly, what happens on the client side is of no concern to MVC. :-) It does not know whether the call was made by the browser engine or the ECMA script.
And since you are asking about Ajax call, the responsibility with dealing with the result falls onto your script (or whatever JS framework you're using).