Validation of ViewState MAC failed and Page.MaintainScrollPositionOnPostback - asp.net

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();
}

Related

Inherited an ASP.NET app & have some simple questions

I'm a PHP/Rails developer and have inherited an ASP.NET application (and its maintenance). So I have a few simple questions.
1.) What's the makeup of a typical rendered(compiled?) HTML page in ASP.NET. That is, when a request is made what happens from the initial request to the time the HTML is displayed in the browser? I'm assuming some templates are combined and finally rendered but I'd like a more in-depth answer.
2.) I've been asked to remove a link from a Login form which is an aspx page. Looking at the aspx page itself it has an inherit statement, a link to the codebehind file, and links some other resources. Where do I actually remove the link from the Login page/template at? I've so far been unable to find exactly where the link is written so that I can remove it or comment it out.
Thank you!
That is, when a request is made what happens from the initial request
to the time the HTML is displayed in the browser?
I'd start learning about the ASP.Net Page Life Cycle.
I've so far been unable to find exactly where the link is written so
that I can remove it or comment it out.
I wouldn't do anything until you have at least a decent grasp of how ASP.Net works. It would be good to run through a few tutorials. ASP.Net has a nice Get Started section.
What's the makeup of a typical rendered(compiled?)
To give you a very simple instructions (trying) to help you fast understand it:
There is a page with the aspx tags, the asp.net is running the code behind and fill this tags with data.
After the filling with data on code behind, the asp.net is "running" the full page and if you have <% %> inside the aspx page, addition code runs that exist inside that.
This is a simple example:
public partial class Dokimes_StackOverFlow_Diafora : System.Web.UI.Page
{
public string cRenderMeAlso = "test";
protected void Page_Load(object sender, EventArgs e)
{
txtText.Text = "One Test";
}
}
<form id="form1" runat="server">
This will fill when the page is prepared
<asp:Literal runat="server" ID="txtText"></asp:Literal>
<br />
This will be render as the page reads out to send it to the browser
as php do
<%=cRenderMeAlso%>
</form>
Now in the place of the Literal control, you can have a full custom render control, that maybe a new complex part of a page with his elements and render.
Each page, master page, user control have a cycle of calls to help first pass all from Init() and prepare them, then pass all from Load(), and the other stage, giving the ability to initialize them in parallel - together.
Now, on PostBack the page have been keep some information's on ViewState that are posted together with the rest post data, and the Code behind use all that data to fill the controls. Also its fires on code behind any click event you have initialize on buttons and you can run some code there to do your work.
I've been asked to remove a link from a Login form
if you can not find that link is maybe on the standard login form that asp.net gives, the solution to that is to render the full template of the form, and remove it from there - but because there is the case to break the Login form, is better to not remove it and just hide it - because if you remove it and the code behind ask for it, it will throw an error - I mean for the standard asp.net forms login code that is part of the asp.net.
So if this is the case, render the login control as template (from design mode, do that on properties), see the link you search and ether make on code behind Link.Visible = false, ether remove it and delete on code behind all the reference on it.

ASP.NET 3.5 validation groups not working

I wish I could paste in my markup, but it's too complex and contains a lot of references to the client's company name. I am hoping someone with vast experience might be able to point me in the right direction.
We have a master page with a ValidationSummary that is not part of a validation group. On our content page, we have another ValidationSummary that is assigned to a validation group called ValReject. On the content page is also a CustomValidator that uses ClientValidationFunction and a button, both of which are also assigned to ValReject.
When I click the button, the client function executes once, but the error reports to both validation summaries, the one on the content page and the on on the master page. I even added a third validation summary and set its group to something like "asdf", but it gets reported to, as well, meaning all three validation summaries are showing the same error on the page.
I then created a separate ASP.NET test project, pasted all the code in, and ran it and it validates like it should.
I then played around with AutoEventWireup on the content page. When I set it to false, validation works, but the page load event doesn't fire. What's up with that?
I know you probably need code samples, but, like I said, I just can't do that without going through a huge headache (trust me, the master and content page markup is huge.
The question here is: Does anyone have an idea of what could cause a single validator to report to ALL validation summaries on the page even though only one of them shares the same validation group as the validator and button?
edit: When I pasted the markup into my test app, I did have to remove some tags to get it to work since the test app doesn't have references to some assemblies used by the real master page. Some things I removed are:
<%# Register Assembly="RadMenu.Net2" Namespace="Telerik.WebControls" TagPrefix="radM" %>
<radM:RadMenu ID="RadMenu1" runat="server" DataSourceID="smdsMenu" Skin="CssGrey" ClickToOpen="True" EnableViewState="False" CausesValidation="false" />
So the fact that it works on my test app leads me to the conclusion that we're doing something on our production app that I am not doing in my test app. Yes, I know this is vague, but perhaps a light bulb will go off in someone's head.
Man, after hours and hours of spinning my wheels, I finally figured it out. We use this extension method to disable double clicks of buttons:
public static void DisableDoubleClick(this Button Control)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("if (typeof(Page_ClientValidate) == 'function') { ");
sb.Append("if (Page_ClientValidate() == false) { return false; }} ");
sb.Append("this.disabled = true;");
sb.Append(Control.Page.ClientScript.GetPostBackEventReference(Control, ""));
sb.Append(";");
Control.Attributes.Add("onclick", sb.ToString());
}
This is what was messing up the validation as it was invoking global validation. I fixed this by making the following change:
sb.Append(string.Format("if (Page_ClientValidate({0}) == false) {{ return false; }}}} ",
Control.ValidationGroup == string.Empty ? string.Empty : string.Format("\"{0}\"", Control.ValidationGroup)));
What clued me in was when I set AutoEventWireup to false to see what would happen. This kept the page load event from firing which is where the above extension method was being called. What a needle in the haystack, this problem.
I don't blame anyone for not answering due to lack of details, but I will keep this up in case anyone else can use it.
edit: Thanks to slfan and gbs. I had just figured out the issue and was coming back here to post my answer when I see that you two were essentially tackling my issue from both sides of the problem. The page load event is where the binding was occurring and the extension method being called was messing up the Page_ClientValidate function. Since you both are technically right and I can't award both of you the answer, I hope no one gets upset if I mark my own as the answer here. You two are definitely good at analyzing such issues with minimal details and no code samples. Props.
The AutoEventWireup causes ASP.NET to call the Page_Load event automatically without having to register to an event. An alternative could be to override the OnLoad method. Your page seems to work properly when Page_Load is not called. What do you do inside this method? Some strange data bindings? What if you uncomment this code, will it work then? Like this you could narrow your problem down to the real problem which you are not showing in your question.
Two things I would look for:
1: Any external validation using Page_ClientValidate being done in javascript
2: Any explicit call to Page.Validate() in code-behind

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.

Custom 404 page and Invalid Viewstate errors

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.

Modifying the HTML of a page before it is sent to the client

I need to catch the HTML of a ASP.NET just before it is being sent to the client in order to do last minute string manipulations on it, and then send the modified version to the client.
e.g.
The Page is loaded
Every control has been rendered correctly
The Full html of the page is ready to be transferred back to the client
Is there a way to that in ASP.NET?
You can override the Render method of your page. Then call the base implementation and supply your HtmlTextWriter object. Here is an example
protected override void Render(HtmlTextWriter writer)
{
StringWriter output = new StringWriter();
base.Render(new HtmlTextWriter(output));
//This is the rendered HTML of your page. Feel free to manipulate it.
string outputAsString = output.ToString();
writer.Write(outputAsString);
}
You can use a HTTPModule to change the html. Here is a sample.
Using the answer of Atanas Korchev for some days, I discovered that I get JavaScript errors similar to:
"The message received from the server could not be parsed"
When using this in conjunction with an ASP.NET Ajax UpdatePanel control. The reason is described in this blog post.
Basically the UpdatePanel seems to be critical about the exact length of the rendered string being constant. I.e. if you change the string and keep the length, it succeeds, if you change the text so that the string length changes, the above JavaScript error occurs.
My not-perfect-but-working solution was to assume the UpdatePanel always does a POST and filter that away:
protected override void Render(HtmlTextWriter writer)
{
if (IsPostBack || IsCallback)
{
base.Render(writer);
}
else
{
using (var output = new StringWriter())
{
base.Render(new HtmlTextWriter(output));
var outputAsString = output.ToString();
outputAsString = doSomeManipulation(outputAsString);
writer.Write(outputAsString);
}
}
}
This works in my scenario but has some drawbacks that may not work for your scenario:
Upon postbacks, no strings are changed.
The string that the user sees therefore is the unmanipulated one
The UpdatePanel may fire for NON-postbacks, too.
Still, I hope this helps others who discover a similar issue. Also, see this article discussing UpdatePanel and Page.Render in more details.
Take a look at the sequence of events in the ASP.NET page's lifecycle. Here's one page that lists the events. It's possible you could find an event to handle that's late enough in the page's lifecycle to make your changes, but still get those changes rendered.
If not, you could always write an HttpModule that processes the HTTP response after the page itself has finished rendering.
Obviously it will be much more efficient if you can coax the desired markup out of ASP.Net in the first place.
With that in mind, have you considered using Control Adapters? They will allow you to over-ride how each of your controls render in the first place, rather than having to modify the string later.
I don't think there is a specific event from the page that you can hook into; here is the ASP.Net lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx
You may want to consider hooking into the prerender event to 'adjust' the values of the controls, or perform some client side edits/callbacks.

Resources