Custom 404 page and Invalid Viewstate errors - asp.net

As you all know it seems like ASP.NET applications is always throwing some Invalid Viewstate errors but now i actually find a way to reproduce one at my site.
What is happening is that a user is trying to access a page that doesn't exist and i do a:
if (CurrentItem == null) {
throw new HttpException(404, "Page not found");
}
This will redirect the user to our custom 404 page. This 404 page is just a regular page in our system that we redirect to via web.config. The search functionality is visible on this page. But when i do a postback from this page the error seems to happen. So if you go to for example.
http://alternativeto.net/software/doesntexist
And then use the search form in the upper right corner and type for example Dropbox, hit enter (if you get a auto-suggestion don't click that cause it will just link you to that app) and baam, you get an error that is "Invalid Viewstate" bla bla.
Anyone know how i can fix this? Is it beacuse how i throw the 404 error? I can imagine it has something todo with the redirect to the custom 404 page and the viewstate and asp.net magic is in some invalid state in some way? Maybe i can change something in my web.config to correct this?
Thanks for any help i can get! Want to get rid of as many errors as possible of course :)
UPDATE
Seems like i solved it myself. When MS had that security bug they recommended to change the error redirect to redirectMode="ResponseRewrite" when i changed it to redirectMode="ResponseRedirect" it seems to work fine!
UPDATE 2
But i also realize that i rather want to have the ResponseRewrite solution since it will stay on that URL that got the error and that is much more cleaner. So i would still be happy to find a solution that works with ResponseRewrite.

A search box should ALWAYS use GET, never POST (!!). So don't use postback for searching, decorate your textbox with a form method="get" action="searchpage" and you are home free, and all your visitors will be happier

I had the same issue, I believe it's because using responseMode="ExecuteURL within <httpErrors> uses Server.Transfer which is why the url will not change from e.g. /contact to /404.
This means the action on the main form will remain as /contact and will postback to that page but since we've transfered to /404.aspx it will throw invalid viewstate.
My solution was to set the form action on prerender of the 404 & 500 pages to the path of the request instead of the RawUrl.
protected void Page_PreRender(object sender, EventArgs e)
{
var form = (HtmlForm)this.Master.FindControl("Form1");
if (form != null)
form.Action = Request.Path;
}
Even though this question is pretty old, I had to post this as it might save someone a few hours of headache in the future.

Related

Get url of page on which the error page was clicked in asp.net

I am not sure if this is possible but I have a requirement so had to ask!
I am handling errors/exceptions in Application_Error event in Global.asax.
This is working fine and I am able to get the url in which the error occurred.
I would like to get the page on which this url resided clicking of which in turn gave me this error. You can say 1 level up.
So, for example I have a page say www.example.com/home-loans.aspx on which there is a link which opens www.example.com/problem-url.aspx. Which I click this link www.example.com/problem-url.aspx throws an error and I am able to correctly catch this along with the url www.example.com/problem-url.aspx but I am not able to figure how to capture www.example.com/home-loans.aspx.
If the link is clicked from outside the website (say from a google search) then this value can come as null or whatever is possible.
Please let me know if you need the code for Application_Error event in Global.asax.
Please help!
Thanks in advance!
You may want to consider using the UrlReferrer property:
Request.UrlReferrer
This will give you the URL in the Refered header.
However, the header may or may not always be available.

Validation of ViewState MAC failed and Page.MaintainScrollPositionOnPostback

I know there are at least 20 questions related to "Validation of ViewState MAC failed", but mine is a bit unique (at least i think it is)
My website was working fine before I had introduced this code on code-behind of my master page.
protected override void OnInit(EventArgs e)
{
Page.MaintainScrollPositionOnPostBack = true;
base.OnInit(e);
}
This obviously brings a section of a page into view after postback. After adding this code my website starting giving me "Validation of ViewState MAC failed" exception on click of a button which calls the following JS code.
function SelectorSubmitOld(targetUrl) {
var f = jQuery('form').get(0);
jQuery("#__VIEWSTATE").remove();
f.action = targetUrl;
f.submit();
}
As soon as I comment the code written in code-behind of MasterPage, everything comes back to normal.
The following I tried other than the above mentioned (which was obviously not required)
My application is hosted on just 1 server
Machinekey is present in web.config and removing/changing it did not solve my problem
Setting EnableViewStateMAC=false in web.config or at page level did not solve my problem
My question is, I am unable to understand what is the relation between my code and ViewStateMAC?
Please let me know if you need any further information from my side.
Thanks in advance!!
ASP.NET Web Forms (.aspx) pages are meant only to post back to themselves, not to any other page. In your case, you have A.aspx posting to B.aspx by changing the <form action> parameter at submission time.
What's the scenario you're trying to accomplish by changing the POST URL dynamically? Perhaps we can suggest a better way to do this.
From this post, I would try to remove references to postback posiiton with :
function SelectorSubmitOld(targetUrl) {
var f = jQuery('form').get(0);
jQuery("#__VIEWSTATE").remove();
jQuery("#__SCROLLPOSITIONX").remove();
jQuery("#__SCROLLPOSITIONY").remove();
f.action = targetUrl;
f.submit();
}

Keeping Original URL while being redirected to Error.aspx

There is a question like the one below and Test System says the answer B is correct but it seems as it states that "You must also ensure that the original URL in the browser is not changed", D should be the answer? Could you please enlighten me on it?
The answer B say that is use the ResponseRewrite. In the case of an error the ResponseRewrite all ready have pass and the page have use it, so can not use it again for second time. Eg, if you have a page /super/demo.aspx that url rewrites to -> demo.aspx?a=2&b=1 this have done all ready, and the page demo.aspx have been all ready readed (how to say to the program ? now I have change my mine, and the url rewrites is something else, when all ready has make this call ?).
When inside the demo.aspx throw an error, to use again the url rewrite you need to go to the new page, and the url is going to change.
What (D) can do is to use the Page_Error, that what actually do is to capture errors from all pages on your application, and when the error thow this code reads from the error.aspx page the content and send it to the browser as it is - without change the url, with out make redirect.
Answer could be D if global.asax had a Page_Error event. Page_Error is a page level event

Custom UrlRewriting leads to AjaxControlToolkit UpdatePanels wrong request url on second postback

I'm trying to implement custom urlrewriting in the global.asax of my website and i'm experiencing some troubles with updatepanels from the ajaxcontroltoolkit:
second post back of my updatepanels seems to request the wrong url (ie : if my rewrited url is /en-US/parentPage/myPage.html and the physical url is /default.asp?ln=en-US&page=myPage, the second post back request /en-US/parentPage/default.asp?ln=en-US&page=myPage, which leads to file not found ...)
I dont know if it matter but i desactivated the viewstate on the page by setting Page.EnabledViewState to false.
To implement urlrewriting i used Server.Transfert(physicalUrl, true)
Also i tried to set the form action to my rewritted url to solve the problem but then none of the postback are working anymore even those from controls not in an updatepanel.
How can i solve my updatepanels problem ?
Is it possible to do it with form action set to rewritted url ?
Thanks a lot ;)
i find a solution to my problem, it seems the problem came from the viewstate of the page not being reloaded correctly due to the server.transfert so i implemented a custom viewstate save/load functin as follow and then everything worrked perfectly ;) :
protected override object LoadPageStateFromPersistenceMedium()
{
object viewstate = Session["__VIEWSTATE"];
return viewstate;
}
protected override void SavePageStateToPersistenceMedium(object state)
{
Session["__VIEWSTATE"] = state;
}
I found that Server.Transfer() caused this issue. I replaced with Response.Redirect(). Now it is working fine.

Redirect to webapp default document when another page is specified?

IIS6, ASP.NET 2.0, No Forms Authentication
I'm calling Response.Redirect("~/foo.aspx"), but the default document ("Default.aspx") for my site is appearing. To make matters worse, it only happens intermittently. Sometimes the redirect displays the right page.
I've checked session state, and I don't see any values in the web.config (that is, I'm assuming I'm using the 20-minute defaults).
I wish I had more relevant information to share (I'll do my best to answer any questions).
Any ideas? Why isn't it redirecting to the specified page?
EDIT: I've looked deeeeeper into the code and learned more details.
Ok. There's foo.aspx and foo2.aspx (and the default document, Default.aspx). All pages extend from BasePage, which extends Page.
BasePage has a property named ReturnPage:
protected string ReturnPage {
get {
if (Session["ReturnPage"] == null) {
Session["ReturnPage"] = "";
}
return Session["ReturnPage"].ToString();
}
set { Session["ReturnPage"] = value; }
}
Users click on a LinkButton on foo.aspx, and the click event handler ends with two lines of code:
ReturnPage = ResolveUrl("~/foo.aspx");
Response.Redirect(ResolveUrl("~/foo2.aspx"));
The Page_Load of foo2.aspx has problems, and its error handling calls Response.Redirect(ReturnPage).
When I view the response headers of foo2.aspx, the 302 location is string.Empty (that is, there isn't one). That same response header has the same ASP.NET Session ID as the response of foo.aspx.
And remember -- this is intermittent. Sometimes, you can click on that LinkButton and go effortlessly to foo2.aspx, no problem. You can process the click with the exact same data once, and it will fail. You'll navigate from the default document (Default.aspx, where you were sent by the "bug") back to foo.aspx, click again with the same data (the same row in the grid/table -- the same LinkButton, essentially), and you'll be redirected to foo2.aspx without issue.
Placing a value in the session immediately before a Response.Redirect() is risky.
Changing foo.aspx's Response.Redirect() to the following might retain the session value more reliably:
Response.Redirect("~/foo2.aspx", false);
UPDATE: This ended up being fixed only by moving our session state into SQL Server. See related question: Why/when are session writes vulnerable to thread termination?
When you say:
Sometimes the redirect displays the right page.
Does it just happen, and you are not sure if there are certain pages that are affected by the problem? If this is the case, then you probably have a addressing problem. You can use either a relative path or an absolute path rather than an Application-relative path. I would also guess that you are trying to either direct to a page from a subdirectory on your site or to a subdirectory on your site. If you choose to stick with the Application-relative path make sure that are taking the subdirectory into account. (ex: ~/FooPages/Foo.aspx)
Here is a good reference page I just found:
http://nathanaeljones.com/129/types-of-asp-net-paths/
I'm a little confused here. What exactly are you trying to accomplish? You're getting the default document exactly because the 302 is blank. Your "inconsistent" behavior is almost certainly due to the way you are saving data in the Session.
The real issue here is why you're redirecting when foo2.aspx "has problems". What's the problem here? Why redirect? If you really need to redirect, why is the redirect target changed? Make it a static error reporting page and you'll be fine.
Once you redirect and get a new instance of the BasePage from foo2.aspx, won't that ReturnPage property be null again? Then once your page load errors out and tries to redirect it will be accessing a null string. Maybe try throwing that property in the Session
Session.Add("ReturnPage","~/foo.aspx")
instead of
ReturnPage = ResolveUrl("~/foo.aspx");
Ofcourse you would have to modify that error handling in the page load to grab it out of session rather than the property and you may have to rethink how the whole redirect is working in your system if this turns out to be the issue.
EDIT:
To test this idea about the property not getting set, or getting set correctly....(just to test I am not suggesting you should hard code the path in there), change your getter to the example below, then check to see if it works. Hope this helps, I am curious to find out what the problem is if this is not the issue.
get {
if (Session["ReturnPage"] == null) {
Session["ReturnPage"] = "~/foo.aspx";
}
return Session["ReturnPage"].ToString();
}

Resources