How can I set the ReturnUrl when I am using RedirectToAction? - asp.net-mvc

I have a controller that redirects to another action, e.g.
mysite.com/food/3
This action does a RedirectToAction to an action called Cake and passes in id=3.
If the user is not authenticated at that point, you go back to the loginpage, but the RedirectUrl is /Cake (without any mention of the id) and not /food/3. This causes an error once you log in because firstly it shouldn't be accessed via that url in the browser, and secondly because the parameters have vanished.
Is there a simple way to make sure it redirects to the original URL in the browser, or do I have to write a custom authorize attribute and store a lookup table to get the parent page?

Gonna take a stab at this one.
Food and Cake take id values and redirect parameters and just pass them around freely where they can be used as you see fit.
Food
public ActionResult Food (int id, string returnUrl = string.Empty)
{
// Do work
return RedirectionToAction("Cake", new { id, returnUrl })
}
Cake
[Authorize]
Cake (int id, string returnUrl = string.Empty)
{
// Do work
if (returnUrl != string.Empty)
return Redirect (returnUrl);
return View();
}
A problem arises when a View is finally returned to the client because then you have to somehow get that returnUrl into the form posted when they submit their login info because you want to use it later. So the first step is getting it into the View's form so it's included in the model that gets posted. One way to do that is the ViewBag; another way is pulling it from the query string. I've shown an example of both below.
Option 1:
Login
Login (string returnUrl = string.Empty)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
Login.cshtml
Model.ReturnUrl = ViewBag.ReturnUrl;
Option 2:
Login
Login ()
{
return View();
}
Login.cshtml
Model.ReturnUrl = Request.QueryString["ReturnUrl"];
If this doesn't suffice, comment and I can try to modify this answer further.

The simplest way to make this work is to put the AuthorizeAttribute onto the action method that calls RedirectToAction to short circuit the nonsense of building the wrong URL. The FormsAuthenticationModule uses the RawUrl of the request when it adds the ReturnUrl parameter, so it not possible to modify without building your own custom FormsAuthenticationModule (which you could consider option B). But if you check authorization before you redirect the RawUrl will be correct.
// This ensures it builds the correct ReturnUrl.
[Authorize]
public ActionResult Food (int id)
{
// Do work
return RedirectionToAction("Cake", new { id = id })
}
// This ensures the final destination cannot be accessed
// without authorization.
[Authorize]
public ActionResult Cake (int id)
{
// Do work
return View();
}

Related

Redirect IGrouping<string, model> List to another action in Same Controller

return RedirectToAction("ActionName", new { lst = finalData });
[HttpGet]
Public ActionResult AcionName(IGrouping<string, ModelName> lst)
{
return View("ActionName", lst);
}
i use this code to redirect my list to another action but this is not working.
You can assign the finalData to a Session or TempData variable.
TempData["FinalData "] = finalData;
return RedirectToAction("ActionName");
From this answer: "TempData Allows you to store data that will survive for a redirect. Internally it uses the Session, it's just that after the redirect is made the data is automatically evicted"
Then in your GET Action Method,
Public ActionResult AcionName()
{
var finalData = TempData["FinalData"] as IGrouping<string, ModelName>;
return View("ActionName", finalData);
}
The problem is, if you were to refresh after the redirect, then finalData would be null. So, in that case you use Session["FinalData"] or get the data from the Database in your Get method again. You can go through the answer I have linked for disadvantages of using TempData.

Pass Value from View To Controller in Asp.net MVC

I am trying to pass a message to another view (actually same controller) I can do it well but there is a problem for me..
I am new on web and it doesnt seem good ..
and here my c# code
if (createStatus == MembershipCreateStatus.Success)
{
string registrationMessage = "You have registered successfully";
return RedirectToAction("KurumsalGiris", new { message = registrationMessage });
}
[AllowAnonymous] //sonradan eklendi
public ActionResult KurumsalGiris(string message="")
{
if (User.Identity.IsAuthenticated)
return Content("Zaten giriş yapmışsınız");
ViewBag.RegistrationMessage = message;
return View();
}
and here html side
#model E_Cv.Models.LogOnModel
#{
ViewBag.Title = "Kurumsal Giriş";
}
<h2>Kurumsal Giriş</h2>
<h2>#ViewBag.RegistrationMessage</h2>
<p>
Please enter your user name and password.
#Html.ActionLink("Yeni Kurum Kaydı", "KurumsalKayit")
if you don't have an account.
</p>
so I dont know how to pass value to another view with different way.. I dont want to show this kind of message on address bar and user musnt change it.
Secondly Could I do it with "Get" Method?
Why don't you just return a different view rather than redirecting? In fact, the code the posted in the first place should be posting to a controller that returns a view for a successful login.
In fact, why are you redirecting to a page that asks the user to login if they've just logged in?
Other possible options include encrypting the string in the URL, or just passing a flag in the URL that the controller translates into the corresponding string.
What you would do is instead of returning a RedirectToAction
you could return the View directly: (second parameter is a model, where you can use the same model class E_Cv.Models.LogOnModel adding a RegistrationMessage property to it)
return View("<name of the view>",
new E_Cv.Models.LogOnModel {
RegistrationMessage = "You have registered successfully"
});
or keep the data in the ViewBag like you have done:
ViewBag.RegistrationMessage = "You have registered successfully";
return View("<name of the view>");
regarding your last question, give the message is showing in your URL, you are using the GET method, if you return a View instead of a redirect, it'll avoid showing anything in the URL
You should use TempData in this scenario
if (createStatus == MembershipCreateStatus.Success)
{
TempData["Message"] = "You have registered successfully";
return RedirectToAction("KurumsalGiris");
}
And then in your view
#if (TempData["Message"] != null)
{
<h2>#TempData["Message"]</h2>
}
Or if you want to do it in the controller, just keep your view the same as it is at the moment and set ViewBag.RegistrationMessage in the controller
ViewBag.RegistrationMessage = TempData["Message"];
If the question is how to pass data between controllers without using the querystring, then one option is the Session object.
if (createStatus == MembershipCreateStatus.Success)
{
Session["Message"] = "You have registered successfully";
return RedirectToAction("KurumsalGiris");
}
[AllowAnonymous] //sonradan eklendi
public ActionResult KurumsalGiris(string message="")
{
if (User.Identity.IsAuthenticated)
return Content("Zaten giriş yapmışsınız");
ViewBag.RegistrationMessage = (string) Session["Message"];
return View();
}
However, I agree with #Jonathan Wood below that this is not necessarily the best approach to the particular problem you are attempting to solve. Still, as a general technique, it is worth knowing about.

Pass information back to the view when using Redirect()

I am calling a controller from more than one page and am using a returnUrl parameter to return the correct calling location:
public ActionResult EmailOrder(int id, string returnUrl)
{
var message = "The order has been emailed";
if (!string.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
return RedirectToAction("Details", new { id, message });
}
How can I pass additional information back to the view when using Redirect(url)? In the above example, I want to be able to pass message back when returnUrl has a value.
If you are redirecting to another action method and you want to pass data that can be access in the new action method, you should use the ASP.MVC Controller TempData property. You use this as follows:
[HttpPost]
public ActionResult MyActionMethod(Order order)
{
// write your logic here to save the Order
TempData["message"] = "here is some message";
return RedirectToAction("Index");
}
Data in the TempData member will be preserved across a redirection. It will be accessible in the redirected page, and then will be removed. Once you read an entry in TempData, it will be marked for deletion.
public ActionResult RedirectedMethod()
{
//Retrieve data from TempData. It will then be marked for deletion
var data = TempData["message"].ToString();
}
If you want to get a value without marking it for deletion, you can use the "Peek" method:
var data = TempData.Peek("message")
Also, you can manually preserve a value that would otherwise be deleted by using the "Keep" method:
TempData.Keep("message")
TempData is of type TempDataDictionary.
Note that TempData uses ASP.Net Session state behind the scenes, so you must have session state turned on if you are using TempData.
For more information on TempData, see here.

ASP.NET MVC session lost between page loads

I am trying to use session state in MVC and I have been stuck for the entire evening!
I realise session state should be used sparingly in MVC - but I am sure I want to use it for this one page - so would appreciate solutions rather than opinions.
Basically, I have a contact form with a CAPTCHA image. When the page loads I want to set the session to the characters used in the CAPTCH image (dynamically generated image).
I have an 'new image' link which async creates a new code, sets the session and dynamically loads a new image to screen.
The session stays sets as long as the page doesn't load or reload. I need to be able to validate the user input against the code in session (which should reflect what is displayed to the user) but the session is empty.
If I perform an AJAX reload on the image i.e. set the session asynchronously - the session is set when I perform a post!!
What's going on?
I need to be able to persist the session value - arrrhhhh!
I have this is a base controller:
public new HttpContextBase HttpContext
{
get
{
HttpContextWrapper context = new HttpContextWrapper(System.Web.HttpContext.Current);
return (HttpContextBase)context;
}
}
and in the controller I have:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Contact(ContactForm c, string button)
{
string sessCaptcha = HttpContext.Session["CAPTCHA_Contact"] == null ? "" : HttpContext.Session["CAPTCHA_Contact"].ToString();
}
Any ideas????? pretty pls with a cherry on top :)
Thanks!
I am so embarrased right now...
Never ever set a session value before a Response.End() (and i believe also the same applies to response.redirect).
OMG - that's 4 hours I will never ever get back again!
Here is the demo code to illustrate my ineptitude...
public ActionResult Page1()
{
Session["test1"] = "hello world";
// This means the session won't be set
// It's is used in valid circumstances..e.g. setting session, then dynamically generating an image based on that value.
Response.End();
return View();
}
public ActionResult Page2()
{
ViewBag.Test = Session["test1"].ToString();
return View();
}
[HttpPost]
public ActionResult Page2(FormCollection fc)
{
ViewBag.Test = "...is still..." + Session["test1"].ToString();
return View();
}
You may want to look into using the TempData object
http://blog.donnfelker.com/2010/02/26/aspnet-mvc2-tempdata-now-persists/

Passing ArrayList parameter to controller action ASP.NET MVC

I am writing an application wherein I need to send a System.Collections.ArrayList data as a parameter from one controller action to another.
I am using
return RedirectToAction("action1","controller1", new { arrList = arrListInFirstAction});
But since the ArrayList goes out of scope in the first action, the parameter in the redirected to action receives a null parameter.
Can someone please help me find an answer to this problem.
Thanks.
you can not send complex types as route parameters. you can, however, use TempData collection to keep that object for one request and on next request it will be automatically removed from collection
publci ActionResutl action()
{
TempData["arr"] = new int[]{1,2,3};
return RedirectToAction("action1");
}
Public ActionResult action1()
{
int[] arr = TempData["arr"];
return View();
}

Resources