ASP.NET MVC partial views and redirecting - asp.net

I have a partial view called Login.ascx that has my login boxes that I include on a number of pages throughout my site. It works fine when the information is correct but I'm trying to do validation so if the login info is incorrect, I want to redirect the user back to the view they were in before to show them the login errors. What is the correct way of saying, return to the view you came from?

If a login fails from any page, I think I would direct them to a login view for the errors instead of the previous page. A dedicated login page is likely to have more UI space to display errors, etc. than a login control on another page. Having said that, you may want to include a returnUrl parameter to the Login action so that when the login is actually successful, the user is directed back to the place they were (or were attempting to get to).

Sounds like instead of asking how I do this, you should be asking yourself WHY am I doing it this way. Maybe it's a design decision rather than a technical question.
Though if you're really going to have one controller actions for multiple login pages you can try...
return Redirect(Request.UrlReferrer.ToString());
Or keep the route name in TempData and just use a RedirectToRoute(TempData["LoginRoute"]);
Both solutions have a bad code smell though.
Note that if you're not checking for cross-site injections that is just going to refer back to the other site. You may want to do some validation on the referring URL.

For the built-in Login method of the AccountController there is a parameter named returnUrl which you can use like so:
Return Redirect(returnUrl);
or
Return RedirectToAction(returnUrl);
if you specify the returnUrl parameter as a valid actionlink.
I recently had similar problems - you might be able to find something here...

Related

Detecting redirect to a different URL

I am using ASP.NET MVC with AngularJs framework. In my home controller I'm checking if there is a valid license and if not, I'm re-directing to a page to import license with this code:
public ActionResult Index()
{
var retVal = _licenseProvider.ValidateExistingLicense();
if (!retVal.Item1)
{
Response.Redirect("DataMaintenance/ImportLicenses", true);
return View("DataMaintenance/ImportLicenses");
}
So, in my ImportLicenses controller I want to detect that I was re-directed vs. called from the menu. I found an older thread about redirecting to a different action, but that solution doesn't apply. What are my options here?
You have a couple of options here:
Add a query string parameter in the ImportLicenses action that
determines whether the user got here via a redirect or the menu
Set a TempData variable before redirecting your user to the
ImportLicenses action.
Use a Session variable
Read this for more information about passing data between Action methods.
It really depends on your constraints, there are a number of options. Without knowing much about your project. My first suggestion would be to drop a cookie before redirecting, then when the request comes in to the ImportLicenses action you can check for the check, and delete it, but include whether or not the cookie was found in your view model so you can reflect this in the UI.
There are other options like using session state, or a query string parameter. A querystring parameter could be just as effective as the cookie idea i mentioned above, and it would be a bit cleaner.
If you can provide more information about your use case, I may be able to expand my answer.
Hope this helps.
In the meanwhile I decided to do a little bit of cheating, but it worked. In the menu I changed the original call to this
dataMaintNodes.SubNodes.Add(new MenuMapNode() { LabelKey = "importLicense", Action = "ImportLicenses", Controller = "ImportLicenses", Area = "DataMaintenance", Icon = "", Roles = "IMPORTLIC" });
In other words, instead of normal Index action I introduced a different action. I added that new action to my controller and just set the ViewBag property to false when called from the menu and to true in the Index action that is called by Redirect. So, it's a cheating, but it works. I only wanted to display Cancel button on that modal dialog when I am calling from the regular menu and no Cancel button when called from the home controller. Now, my second problem is that Modal Dialog doesn't really prevent from escaping from it and continuing working with the application. So, we may want to introduce more logic.

make action method only accessible through redirect

I'm trying to submit a form. When the form is submitted I want the form to dissapear and the text Thanks for your support. An e-mail will be sent to you as soon as possible. to show.
I think the most logical way to go by this is by making the form submit to the action SaveMessage() that redirects to the action RedirectToAction("MessageSaved") that returns the view with the message. If it isn't, please say so. This is for practice.
The problem is that the message can be viewed as well by going to /Support/MessageSaved. How do I prevent users from accessing it by url, but make the action accessible by redirectToAction()?
Set a value in TempData before the redirect. In the MessageSaved action method, check for that value before showing the form. Otherwise, redirect to another page.

What is the alternative to Response.Redirect() asp.net?

Hi One of the tips in "website performance tips" in various blogs says "Avoid Redirects". In my case, I am using Response.Redirect for the same page. I am passing a querystring and displaying appropriate information to the user.
Response.Redirect("FinalPage.aspx?NextID=" + ID);
So in our business logic, i am reloading the same page with different information.
So how do i avoid redirect? Is there any other alternative? BTW, my aim is to gain some performance there.
Redirect is the R in the PRG pattern which is an accepted pattern for processing posted requests. So it is definitely not evil.
However, there used to be a common interview question: "What is the difference between Server.Redirect() and Server.Transfer() and which one must be used?". People used to say Transfer because it did not involve a round-trip but web has changed so much since then. In those days you could not re-use the the common logic in the views unless you use Transfer or Redirect, but nowadays especially with ASP NET MVC there are tons of a ways to do that.
In your case, I am all for PRG and I believe redirect is semantically more correct. Also it prevents the form being re-submited if user clicks F5 or refresh.
The recommendation is for unnecessary redirects.
Your case is different - you are passing in information to the page, this is not strictly the same thing as a regular redirect (i.e. a page that moved).
You can also do a Server.Transfer, which does not require a new request to come in, thus lessening the load on the server. More information comparing the two is here.
In your case, you do want to do a Redirect because you are modifying the query string and changing something on the page, as opposed to shifting processing of the initial request to another page.
The main "evil" if it could be called such is that redirects require an extra round trip; the client requests one page (usually the same page, specifying that a particular button was clicked), and the server responds saying "request this page instead", and the browser then complies, resulting in the server actually serving up the next page.
It's sometimes necessary to do this, however there are now much better ways to control navigation in a website. For instance, instead of a "form" button that causes a postback and redirect, you could use a LinkButton that will behave like a hyperlink, allowing the browser to request the new page directly. You could also use a MultiView that shows different ASCXs, and control navigation by view-flipping (however, understand that this can have its own performance implications, especially when using them in a nested fashion).
I think if you want to redirect to same page then instead of doing Response.Redirect("FinalPage.aspx?NextID=" + ID); you could use NextID in ViewState also or Hidden Field so that you would not required to redirect SAME page and then check that hidden field or viewstate instead of checking QueryString
:D

How do I use the "Post/Redirect/Get" a.k.a. "Redirect after Post" with asp.net

Doing a refresh after certain action in asp.net seems to make them happen again even when that action doesn't make sense (think double delete). The web way to deal with this situation is to redirect after a post to get a clean version of the page that can be refreshed without reposting an action to the webserver. How can I do this with ASP.NET
I have a feeling there is a deeper problem I'm not getting but here goes. In your postback event:
// the post handling logic, e.g. the click event code
Response.Redirect(Request.RawUrl);
Use Server.Transfer method.
The Server.Transfer method has a second parameter—"preserveForm". If you set this to True, using a statement such as Server.Transfer("WebForm2.aspx", True), the existing query string and any form variables will still be available to the page you are transferring to.
http://www.developer.com/net/asp/article.php/3299641

How do I remove a page from the browser history?

I have an have an ASP.Net page which contains a button. This Page contains a ServerSide Paypal button.
When pushed my server does various clever things on the back end and then rewrites the response as a form and some javascript which posts this form to paypal..
This all works great.
However, if the user then elects to click back, they will arrive at my generated self-posting form and that will forward them again to Paypal.
I thought if I could find a way to have my generated form page not exist in the history, then this will solve my problem. but I have no idea how to correct this.
How can I remove my page from the history or just have it never appear?
Update: Thanks to all... Those are some great answers. Upvoted all good ones but went with splattne on account of clever use of hidden field rather than cookies for basis of decision.
window.location.replace(URL);
window.location:
replace(url)
Replace the current document with the
one at the provided URL. The
difference from the assign() method is
that after using replace() the current
page will not be saved in session
history, meaning the user won't be
able to use the Back button to
navigate to it.
I'm not sure if that can be done. But here is an idea how you could prevent that resubmit of the form.
You could insert a hidden input in your form which at the beginning would be empty. On submit you'll write a value in that field and make sure you check on every submit attempt if this field is empty.
If it is not empty on submit you know that the form was previously sent and you could warn the user.
As a web application, you'll never have full control of the user's browser. Even if there was a way to instruct the browser to not store the page in history, which I doubt, you can't be sure it'll work. For example, a clever user could tweak an open-source browser to store every page in history, no matter what.
I think you should try to approach the problem from another angle. You could, for example, detect that it's the same form which is being forwarded and not send it to paypal the second time. The important thing is to do it server-side.
Perhaps you could set a cookie before submitting the form.
When the page is loaded, check for the existence of that cookie (meaning the form was already submitted). If found, instead of automatically submitting the form, automatically go back (window.history.back()) again.
I'm not sure if you can do this easily with PayPal integration, but the
"Post / Redirect / Get" pattern can be used to address this problem
A useful Hint for some might be this...
window.history.go(-2);
particularly in the advent of a load failure warning popup.
You could simply programme your page not to submit, or to do something / navigate somewhere else, if window.referer is the Paypal page you are trying to avoid invoking a second time.
protected void Page_Load(object sender, EventArgs e)
{
Page.RegisterClientScriptBlock("", "<script>if(history.length>0)history.go(+1);</script>");
}

Resources