I want to achieve what stackoverflow does with url.
domain.com/questions/1234/properTitle <-- fine!
domain.com/questions/1234/wrongTitle <-- redirect to domain.com/questions/1234/properTitle
But I don't want to contact the database twice.
For example, inside the question controller action, I am already querying all the info based on 1234 question Id. I do not want to redirect and lose all this information and then query again. Should I put it in TempData or something? What efficient way to handle this?
I think it's more complicated (and maybe even less efficient) to manually cache and retrieve the data in your application. Your database server probably caches the result anyway and the second query won't take very long.
Update: You can redirect to an overloaded action with the model as an argument. This could look somewhat like this:
return RedirectToAction("Action",
new {
id = 1234,
title = "properTitle",
model = myAlreadyRetrievedModel
});
Related
After a user has completed a form in MVC and the post action is underway, I am trying to redirect them back to another view within another model.
Eg. This form is a sub form of a main form and once the user has complete this sub form I want them to go back to the main form.
I thought the following might have done it, but it doesn't recognize the model...
//send back to edit page of the referral
return RedirectToAction("Edit", clientViewRecord.client);
Any suggestions are more that welcome...
You can't do it the way you are doing it. You are trying to pass a complex object in the url, and that just doesn't work. The best way to do this is using route values, but that requires you to build the route values specifically. Because of all this work, and the fact that the route values will be shown on the URL, you probably want this to be as simple a concise as possible. I suggest only passing the ID to the object, which you would then use to look up the object in the target action method.
For instance:
return RedirectToAction("Edit", new {id = clientViewRecord.client.ClientId});
The above assumes you at using standard MVC routing that takes an id parameter. and that client is a complex object and not just the id, in which case you'd just use id = clientViewRecord.client
A redirect is actually just a simple response. It has a status code (302 or 307 typically) and a Location response header that includes the URL you want to redirect to. Once the client receives this response, they will typically, then, request that URL via GET. Importantly, that's a brand new request, and the client will not include any data with it other than things that typically go along for the ride by default, like cookies.
Long and short, you cannot redirect with a "payload". That's just not how HTTP works. If you need the data after the redirect, you must persist it in some way, whether that be in a database or in the user's session.
If your intending to redirect to an action with the model. I could suggest using the tempdata to pass the model to the action method.
TempData["client"] = clientViewRecord.client;
return RedirectToAction("Edit");
public ActionResult Edit ()
{
if (TempData["client"] != null)
{
var client= TempData["client"] as Client ;
//to do...
}
}
I have a gsp form which displays the list of employees with the details (ie., Employee Name,Designation,Department,Status). All these columns are sortable. After calling a specific action in my controller class (ie., Changing the status of the employee from active to inactive and vice versa) the sorting gets disturbed. I am using the following code to sort while retrieving from DB
String strSort = params.sort ?: "empId";
strSort += " "
strSort += params.order?: "asc";
Is there any way I can retain the sort order which was there before posting a "Status change" action? If it is how it can be achieved?
As suggested by rvargas, it is possible through a variety of methods. queuekit plugin isn't released properly as yet so you could clone grails 3 / grails2 branch depending on which it is you are working with and also clone the test site to go with it to mess with this concept within the plugin:
In short You need to separate out your search feature and you can do this via a session value or send it as a subset list iteration.
I decided to not use sessions. Then when I click delete The bean is bound back in with the request sent (which be the id to delete)
At the very end it relists so no need to do any other here:
The most important bit being when I call the ajax reloadPage or even further postAction used by delete function is that I serialize search form. The actual search object is kept in a tidy manner here
But if this is too complex then in the very controller link the session search was commented out. I think you could just enable that forget all this complication and have a searchAgain() feature which renders the _list template like it does if it is xhr in my controller and rather than binding bean it binds the session.search map instead and if you did go down this route you probably want to change from g:render to g:include action="searchAgain"
Hope that helps you understand better
I can think of two ways to do it:
Pass your sort and order parameters to your action and send them back
with the result.
Store in session both parameters every time you update them.
To store and retrive from session use something like this:
private DEFAULT_SORT = 'myDefaultSort'
def myAction() {
if (params.sort && params.sort != session.getAttribute('sort-' + actionName)) {
session.setAttribute('sort-' + actionName, params.sort)
}
params.sort = session.getAttribute('sort-' + actionName)?:DEFAULT_SORT
...
//Your existing logic
}
If you receive a new/different sort parameter you save it into session. Then you try to load existing parameter from session, if you dont have any value stored, you get a default value.
i am teaching myself MVC and am struggling to work out the best solution to my problem. I have a search controller with a large amount of input fields. I will also have multiple overloads of the search fields eg basic search advanced search searchByCategory etc.
When the search form is posted i redirect to another action that displays the search results. If i press f5 the get action is fired again as opposed to the search results being refreshed in the action that my post redirects to. Ideally i would like to redirect to a search results Action Method without using the query string, or detect when refresh is hit and requery the database and just use different actions within the same search controller. I have read a lot of posts about this and the only 2 solutions i can find is using a session variable or TempData.Can anybody advise as to what is the best practice
From the Comments
Most of the time I prefer to use TempData in place of QueryString. This keeps the Url clean.
Question
Can anybody advise as to what is the best practice
Answer
Once the data is sent to Action Method to get the results from Database after then As per my knowledge you can use TempData to store the posted data. It is like a DataReader Class, once read, Data will be lost. So that stored data in TempData will become null.
var Value = TempData["keyName"] //Once read, data will be lost
So to persist the data even after the data is read you can Alive it like below
var Value = TempData["keyName"];
TempData.Keep(); //Data will not be lost for all Keys
TempData.Keep("keyName"); //Data will not be lost for this Key
TempData works in new Tabs/Windows also, like Session variable does.
You could use Session Variable also, Only major problem is that Session Variable are very heavy comparing with TempData. Finally you are able to keep the data across Controllers/Area also.
Hope this post will help you alot.
I think there is no need to even call Get Method after performing search although its good habit in case of if your are performing any add/update/delete operation in database. But in your case you can just return the View from your post method and no need to store data in tempdata or session until you really don't need them again. So do something like this:
[HttpPost]
public virtual ActionResult PerformSearch(SearchModel model)
{
// Your code to perform search
return View(model);
}
Hope this will help.
Hi thanks
I have had a chance to revisit this. the problem was i neglected to mention that i am using jQuery mobile which uses Ajax by default even for a normal Html.BeginForm. I was also returning a view which i have since learned will not updated the URL but only render new html for the current controller. my solution is to set the action, controller and html attributes in the Html.Beginformas follows :
#Html.BeginForm("Index", "SearchResults", FormMethod.Post, new { data_ajax = "false" })
inside the parameters for the index action of the searchResults controller I have a viewModel that represents the fieldset of the form that i am posting. The data-ajax="false" disables the Ajax on the form post and MVC takes care of matching the form post parameters to my model. This allows the url to update and when i press f5 to refresh the controller re-queries the database and updates the search results.
Thanks everybody for your help. I was aware of TempData but it is good to know that this is preferred over session data so i voted up your answer
In my View, I have a table pulling various data in. Initially it only shows the rows actionable by that user. However, there is also an option to show all rows. To achieve that so far, I have two hyperlinks above the table, with hrefs of "?isRequiredAction=true" and "?isRequiredAction=false". In the Controller, I have the following:
public ActionResult Index(bool? isRequiredAction){
string userId = User.Identity.Name;
bool ira = true;
if (isRequiredAction != null)
{
ira = Convert.ToBoolean(isRequiredAction);
}
...
return View(model);
So, right now the Controller is getting its parameter from the querystring created by clicking those links. I'm not satisfied with this approach since I don't want to dirty up the URL with this query. Is there a simpler way of achieving what I'm asking? We would like to avoid turning the links into form objects if possible. Thanks.
This MSDN article should help.
From view to controller, you can do a HttpPost or you can pass the data as parameters.
You can create two distinct custom routes, for example:
www.yourapp.com/home
www.yourapp.com/home/showall
After that, you can make both routes target the same action or create a distinct action for each of these routes. Your choice!
Technically, I don't believe there is very appropiriate solution that fits your need because you don't want to make the link form object, nor "dirtying up" the URL. I suggest you to stick with your first approach because there is nothing wrong with dirtying the URL. By "dirtying" your URL, you can make link bookmarkable. If you are really concerned with it, then you can have two choices:
(1) Use Ajax. This way your URL will be unaffected; however, you lose bookmarkability.
(2) Use URL rewriting to make your URL "pretty". This approach, under the hood, equals to "dirtying up" the URL, but in a "pretty" way.
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.