MVC Create URL Back to Original Page on Timeout - asp.net-mvc

In my Controller I have a function which helps me check for any Session timeouts, this works fine and it directs the users to an error page. Unfortunately from here I really just have the option to go back to the homepage, what I would like is to create the functionality to take them back to the previous page.
Each page will have a form of ID attached in the query string (this isn't always called ID, but it is always a unique number to identify the object.
What I need is to try and get this ID (always the first parameter / key) and use this as a basis to create the ActionLink on the view. I can get the RawUrl using the ActionExecutedContext which contains the requesting raw URL, but I'm unsure how to actuall make this useful.
The following is the code which executes after my Action, it validates if the user has timed out and moves them to an error page. The ErrorId of -1001 is just to identify that this is a timeout. What I need is an ID, similar to what I can kind of see in the RawUrl property, which I can then use as part of the RedirectToAction to take the user back to the original page.
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Session != null)
{
if (filterContext.HttpContext.Session.IsNewSession)
{
string cookie = filterContext.HttpContext.Request.Headers["Cookie"];
if ((cookie != null) && (cookie.IndexOf("ASP.NET_SessionId") >= 0))
{
filterContext.Result = RedirectToAction("Error", new { errorId = -1001, errorMessage ="Your session has timed out.Please restart the application or click 'Home' below."});
return;
}
}
base.OnActionExecuted(filterContext);
}
}

... and it directs the users to an error page.
When making this redirect pass as query string parameter a ReturnUrl. This parameter will be the current request url.
Then inside the error page you will be able to use this ReturnUrl query string parameter to build an anchor or a form pointing to the initially requested resource. For example:
Go back

Related

Request.UrlReferrer.ToString() Not reload in IE only

I'm trying to redirect page on previous page when i click on currency menu. In this menu set selected currency in cookies and redirect to Request.UrlReferrer.ToString() so Request page automatic read cookies and apply currency.
Here is my code
public ActionResult Index(string currency)
{
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Values["CODE"] = currency;
cookie.Values["sym"] = Currencies[currency];
cookie.Values["Name"] = CurrenciesName[currency];
string currencyname = GetCurrencySymbol(currency);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return Redirect(Request.UrlReferrer.ToString());
//return RedirectToRoute(Request.UrlReferrer.ToString());
}`
for example page1 have some item with amount in USD now user change currency then i send request to CurrencyController with above Action then return to same page1.
Above code working fine in all browsers but not working in IE 11.
give me some idea where I'm doing wrong.
Thanks
First and foremost, you should never rely on UrlReferrer. Its value comes from an HTTP header that is not guaranteed to be sent, and even if it is sent, it can be tampered with. By using it in the way you are, you're opening yourself up to CSRF and man-in-middle attacks.
The correct way to do something like this is to pass along the URL you want to return to. For example, if a user is on a URL like /foo/ and then clicks a link where you want to redirect them back to /foo/ afterwards, then the URL of the link should be something like: /bar/?returnUrl=/foo/.
Then, the action responding to /bar/ would do something like:
public ActionResult Bar(string returnUrl)
{
// do something
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
// redirect to default
}
The Url.IsLocalUrl check is to make sure that the return URL is a path on the current site, again, to prevent malicious attacks.

RedirecttoAction with error message

I have a link on a grid in my AdminUsers view
grid.Column(header: "", format: (item) => (condition ? Html.ActionLink("Impersonate", "Impersonate", "Admin", new { id = item.username }, null) : Html.Label("Impersonate"), style: "webgrid-column-link"),
In the controller, I have
public ActionResult Impersonate(string id)
{
string result = ORCA.utilities.users.setImpersonation(id);
if(result == "nocommonfields")
return RedirectToAction("AdminUsers", "Admin");
else
return RedirectToAction("terms_of_use", "Forms");
}
How can send an error message to display when I return to the AdminUsers page?
You may use TempData
if(result == "nocommonfields")
{
TempData["ErrorMessage"]="This is the message";
return RedirectToAction("AdminUsers", "Admin");
}
and in your AdminUsers action, you can read it
public ActionResult AdminUsers()
{
var errMsg=TempData["ErrorMessage"] as string;
//check errMsg value do whatever you want now as needed
}
Remember, TempData has very short-life span. Session is the backup storage behind temp data.
Alternatively, You may also consider sending a flag in your querystring and read it in your next action method and decide what error message to show.
The TempData controller property can be used to achieve this kind of functionality. Its main drawback in my opinion is that it uses the session storage in to store its contents. This means that you'll have extra work getting it to function on a web farm, or that you need to turn on sessions in the first place.
The good thing about TempData is that is exactly does what you want. Its a string based dictionary and you can put anything in it and by default get it out only once. So before calling RedirectToAction() you set your message. On the next request you check for messages and display them. By retrieving the messages they are automatically deleted at the end of the request.
As an alternative you could use cookies for transporting the message between the two requests. Essentially you could either roll your own solution, or implement a custom ITempDataProvider which transports the contents of TempData via cookies. Note that you need to properly secure cookies. MachineKey.Protect() can help you if you are rolling your own.
I was facing the same problem you did and created a solution for it called FlashMessage. Perhaps this could save you some work. It's available on NuGet as well. Usage is simple: you simply queue a message before you call RedirectToAction() as follows:
if(result == "nocommonfields")
{
FlashMessage.Warning("Your error message");
return RedirectToAction("AdminUsers", "Admin");
}
In your view you include the following statement to render any previously queued messages:
#Html.RenderFlashMessages()

redirect to an external url on form submit

i have a form which on submit should redirect to an external URL to perform some action with my form data, as well as remain on the home page after successful submission. i used redirection, but this will make my second option possible, but not my first one. Please help..
You have different possibilities here. The first possibility is to set the action attribute of the form directly to the external url and add a returnurl hidden input parameter. When the form is submitted it will POST data to the external url to process and when it finishes processing the external url will use the returnurl parameter to redirect back to your home page.
Another possibility is to call the external url in your POST action using WebClient to send data for processing and return the same view:
[HttpPost]
public ActionResult Index(SomeViewModel model)
{
using (var client = new WebClient())
{
var values = new NameValueCollection
{
{ "param1", model.Property1 },
{ "param2", model.Property2 },
};
// send values for processing to the external url
var result = client.UploadValues("http://externalurl.com", values);
// TODO: analyze result
}
return View(model);
}
You need to manually program for this. For example you can pass a returnUrl parameter (e.g. via the query string) to the second page and that page will be in charge of reading this parameter and perform a redirect of its own.

How to validate a path in ASP.NET MVC 2?

I have a custom attribute that checks conditions and redirects the user to parts of the application as is necessary per business requirements. The code below is typical:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// ...
if (condition)
{
RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();
redirectTargetDictionary.Add("action", "MyActionName");
redirectTargetDictionary.Add("controller", "MyControllerName");
filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);
}
// ...
base.OnActionExecuting(filterContext);
}
I was just asked to allow the user to choose a default page that they arrive at upon logging in. Upon adding this feature, I noticed that the user can get some unusual behavior if there is no action/controller corresponding to the user's default page (i.e. if the application were modified). I'm currently using something like the code below but I'm thinking about going to explicit actions/controllers.
else if (condition)
{
var path = "~/MyControllerName/MyActionName";
filterContext.Result = new RedirectResult(path);
}
How do I check the validity of the result before I assign it to filterContext.Result? I want to be sure it corresponds to a working part of my application before I redirect - otherwise I won't assign it to filterContext.Result.
I don't have a finished answer, but a start would be to go to the RouteTable, get the collection, call GetRouteData with a custom implementation of HttpContextBase to get the RouteData. When done, if not null, check if the Handler is an MvcRouteHandler.
When you've got so far, check out this answer :)

With ASP.NET membership, how can I show a 403?

By default, ASP.NET's membership provider redirects to a loginUrl when a user is not authorized to access a protected page.
Is there a way to display a custom 403 error page without redirecting the user?
I'd like to avoid sending users to the login page and having the ReturnUrl query string in the address bar.
I'm using MVC (and the Authorize attribute) if anyone has any MVC-specific advice.
Thanks!
I ended up just creating a custom Authorize class that returns my Forbidden view.
It works perfectly.
public class ForbiddenAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (AuthorizeCore(filterContext.HttpContext))
{
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
// auth failed, display 403 page
filterContext.HttpContext.Response.StatusCode = 403;
ViewResult forbiddenView = new ViewResult();
forbiddenView.ViewName = "Forbidden";
filterContext.Result = forbiddenView;
}
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}
}
Asp.net has had what I consider a bug in the formsauth handling of unauthenticated vs underauthenticated requests since 2.0.
After hacking around like everyone else for years I finally got fed up and fixed it. You may be able to use it out of the box but if not I am certain that with minor mods it will suit your needs.
be sure to report success or failure if you do decide to use it and I will update the article.
http://www.codeproject.com/Articles/39062/Salient-Web-Security-AccessControlModule.aspx

Resources