How to fix the issue of Invalid viewstate - c#

I have developed one web application in ASP.NET(Framework 4) with C# and deployed on one external server. As I checked server's log, the Invalid ViewState exception logged periodically. To resolve this issue, I have tried many solutions but non of that worked for me. I don't want to set enableviewstatemac property to false in web.config for security reason. (May be setting this to false will resolve the issue.)
Getting this error even for the pages that contains very small amounts of controls.
Error Description/Stacktrace:
Application_Error | Invalid viewstate.
Client IP: [IP]
Port: 26824
Referer: [URL with parameter]
Path: /page.aspx
User-Agent: Mozilla/5.0 (Linux; Android 8.1.0; SAMSUNG SM-G610F Build/M1AJQ) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/7.4 Chrome/59.0.3071.125 Mobile Safari/537.36
ViewState: /wEPDwUKMTU0MjgwMzYxMg8WAh4HTWVzc2FnZQULbWFsaS1icmlkZXMWAmYPZBYCAgMPZBYCAgEPZBYEAgEPDxYCHgRUZXh0BQZCcmlkZXNkZAIDDxQrAAIPFgQeC18hRGF0YUJvdW5kZx4LXyFJdGVtQ291bnQClQFkZBYCZg9kFioCAQ9kFgICAQ9kFgICAQ9kFg5mD2QWBGYPZBYEZg8VAQ9QaG90b3MvTUc4MC5qcGdkAgEPZBYCAgEPZBYCZg8VAQRNRzgwZAICD2QWAmYPFQEKMTk5Ni0xMC0wMmQCAQ9kFgICAQ9kFgJmDxUBBzVmdCAzaW5kAgIPZBYCAgEPZBYCZg8VAQdEaXBsb21hZAIDD2QWAgIBD2QWAmYPFQEiRGlwbG9tYShDaXZpbCksICBBdXRvIENhZCwgM0RTIE1heGQCBA9kFgICAQ9kFgJmDxUBDE5vdCBFbXBsb3llZGQCBQ9kFgICAQ9kFgJmDxUBDE5vdCBFbXBsb3llZGQCBg9kFgJmD2QWAgIBDw8WAh4LUG9zdEJhY2tVcmwFJX4vcHJvZmlsZS1kZXRhaWxzLmFzcHg/cHJvZmlsZWlkPU1HODBkZAICD2QWAgIBD2QWAgIBD2QWDmYPZBYEZg9kFgRmDxUBD1Bob3Rvcy9NRzc5LmpwZ2QCAQ9k...at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString, Purpose purpose)
Try 1: Used Machine key(key for .Net 4.0) generated by one online tool in config file.
Code:
<machineKey
validationKey='2EEA416CEFC6D6BE856ED57B97FB9CA7DFACE17C073125949A1D682C80A44BB2A
D887DDDC13DBFB0954F1000FEE5757E99693F222F8E28CAA2E6DAB8C4F99E0C'
decryptionKey='877478B2F33A74226ABEF55FDCC1A76E43F1BBEA6241A592'
validation='SHA1' />
<pages enableViewStateMac='true'/>
</system.web>
Try 2: Compressing the ViewState
As code is long, I have added link of the code here that I have tried.Compressing the ViewState
Try 3: MaxPageStateFieldLength property of page in web.config.
In this way, in web.config file, it showing warning as MaxPageStateFieldLength attribute is not allowed.
Code:
<system.web>
<pages MaxPageStateFieldLength="20"/>
</system.web>
Try 4: Place hidden fields for Encrypted Viewstate and Event validation on the top of the form
In this way, I have override the Render event of Page and write the code taken from this link: Link
None of the above solutions worked for me. Please correct me if I have did any thing wrong in above ways. Please ask for any other inputs if more clarification is needed.
Currently I have provided one workaround. I have catched this specific exception in application's error event and redirect to same page that causing this issue. But I am not satisfied with this workaround as issue is still exist.
Workaround:
void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
if (exception != null)
{
if (exception is System.Web.HttpException && exception.InnerException is System.Web.UI.ViewStateException)
{
Response.Redirect(Request.Url.AbsoluteUri);
WriteLog("Application_Error", "Invalid viewstate | Redirect to: " + Request.Url.AbsoluteUri);
}
else
{
WriteLog("Application_Error", exception.InnerException.Message + "|" + exception.StackTrace + "|" + Request.RawUrl);
}
}
// Clear the error from the server
Server.ClearError();
}

Related

Postback Fails On Default Document

So I've created a Web Application (not Web Site) with ASP.NET (C#) and it compiles just fine in the VS13 environment. But when I publish it on IIS, the Postback on the Default Document fails. The Default Document is called LoginPage.aspx. As soon as I click the <asp:Button> to run my code behind, all it does is refresh the page. This project has been published on my local 127.0.0.1 IP address for the time being.
I know this has been a documented issue, but I've tried many solutions and have not come across a resolution. Some solutions I have attempted:
Creating a brand new Web App with minimal code to attempt accessing any Postback with no success.
I tried the first solution presented here with no success: https://stackoverflow.com/a/7367076/4204026
I also tried URL mappings:
<urlMappings>
<add url="~/login" mappedUrl="~/Views/LoginPage.aspx" />
<add url="~/login/" mappedUrl="~/Views/LoginPage.aspx" />
</urlMappings>
I'm honestly at a loss as to what's happening here. One thing I did notice is when the application is being run through Visual Studio, the <form> tag on the LoginPage.aspx appears in Chrome as:
<form method="post" action="LoginPage" id="ct101" class=".myForm">
Through IIS:
<form method="post" action="./" id="ct101" class=".myForm">
Not sure if that's a problem either. I tried hard-coding the action to login to see what would happen and it does redirect to the correct page, but as suspected no Postback was fired - My Session variable returned null and no query string was used.
Here's the related LoginPage.aspx front-end code (trimmed out a bunch of unrelated HTML):
<%# Page Title="DREW KENNEDY | WELCOME" Language="C#" MasterPageFile="Site.Master" AutoEventWireup="true" CodeBehind="LoginPage.aspx.cs" Inherits="MyMedia.Views.LoginPage" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<!-- form is located on Site.Master -->
<asp:Button OnClick="LoginBtn_Click" CssClass="login" runat="server" name="submit" Text="Sign In" />
</asp:Content>
And the LoginBtn_Click method in LoginPage.aspx.cs:
protected void LoginBtn_Click(object sender, EventArgs e) {
//Tried the following line while commenting out everything else to make sure Postback is being ignored
//Response.Write("<script>alert('Test');</script>");
try {
AbstractPersistenceDecorator decorator = new PersistenceDecorator();
string uname = username.Text.Trim();//username is a TextBox Control
string pass = password.Text.Trim();//password is a TextBox control
bool isCookieRequested = CheckBox.Checked;
if (decorator.authenticate(uname, pass)) {//calling SQL Server for authentication
User AuthenticatedUser = (User)Session["User"] ?? decorator.getUserInfo(uname);
if (Session["User"] == null) Session["User"] = AuthenticatedUser;
if (isCookieRequested) {
HttpCookie cookie = new HttpCookie("username", AuthenticatedUser.Username);
cookie.Expires.AddDays(7);
Response.Cookies.Add(cookie);
} else {
Session.Timeout = 15;
}
Thread.Sleep(1600);
//string redirect = string.Format("dashboard?username={0}", AuthenticatedUser.Username);
Response.Redirect("dashboard?username=" + AuthenticatedUser.Username);
}
} catch (Exception ex) {
//who cares?
}
}
Final pieces of info:
Running IIS 8.0
Application created with 4.5 Framework, Application Pool is also 4.5 Framework
I have ensured that ASP.NET is installed on IIS
I do have URL ReWriting in the global.asax file, though I'm not sure if that is related in any way (I don't see how).
I have no Default.aspx page
EDIT:
Just tested the project through 127.0.0.1 on IE11 and FF with the same result.
EDIT #2:
Additional things I have tried with no success:
I tried removing my URL Rewriting
I tried adding an empty URL Rewrite rule, i.e. ("Empty URL", "", "~/Views/LoginPage.aspx")
Additional notes:
I do not use Telerik
I do not use ISAPI
The project in Visual Studio was set to debug and not release
I apologize for not giving enough information in the OP as I have found the answer. It turns out it had nothing to do with ASP.NET, but rather SQL Server. I stripped the code bare and after adding back one piece of code at a time and stripping away all exception handling, I found through IIS that IIS APPPOOL\.NET vX.X did not have permissions to access the database.
What I had to do is:
In MSQLSM, add a new Login for IIS APPPOOL\.NET v4.5
Further on, I found out that it needed the correct permissions to perform certain commands after receiving the following exception:
The SELECT permission was denied on the object 'X', database 'X', schema 'dbo'
This Was Solved Here
Give that new Login the proper access. Login Properties > User Mapping > checking db_datareader and public.
The code behind now executes. It still leaves the question why it was prohibiting any Postbacks, even if I removed any SQL Connectivity in the code behind. Very strange.
Anyway, thanks to those who helped.
I suggest that you redirect from the default page to the Expected page then this should work. Iis default page handling is done through isapi to handle static content so the post data may not survive

Detect site login url in Application_End

I have this entry in web.config
<appSettings>
<add key="pingUrl" value="http://examplesite.com/login.aspx"/>
</appSettings>
I have the below code in Global.asax.cs to automatically start the IIS when it is recycle
void Application_End(object sender, EventArgs e)
{
try
{
string pingUrl = ConfigurationManager.AppSettings["pingUrl"];
WebClient http = new WebClient();
string Result = http.DownloadString(pingUrl);
}
catch (Exception ex)
{
string Message = ex.Message;
}
}
My Question is can I detect the application forms authentication login page url in Application_End method some how? Instead of reading entry from <appSettings/>
Note: I am using Quartz.Net in my MVC4 application and it is stop working when IIS recycle. I read IIS app pool recycle + quartz scheduling and many SO links but no use. We use external hosting provider, so we dont have a control of changing a physical config file.
After reading http://weblog.west-wind.com/posts/2007/May/10/Forcing-an-ASPNET-Application-to-stay-alive I decided to go with this solution.
Check out the MSDN docs on FormsAuthentication.LoginUrl.
If you have your forms authentication set up in web.config's <authentication> element, and you have the "loginURL" populated there, then the property mentioned above should have the information you're looking for.

.NET Retrieving Error StackTrace in Custom Error Page

I am running .NET 3.5 and IIS7.
I was trying to use customErrors to redirect to a custom error page that could still display the exception details, stack trace, etc. I had a hard time getting it to work, trying about 20 different approaches I found online (mostly on stackoverflow), some of which were slight variations of others. I preferred to have the redirect to happen in Web.config because I wanted the custom error page to be easily found/edited outside the code.
Here's what I finally got to work. I'm posting because I tried so many of the more complex approaches I found here and they didn't work for me, and just wanted to post the simple one that ultimately did.
Web.config:
<customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx" redirectMode="ResponseRewrite" />
Without the redirectMode="ResponseRewrite", I could not access the exception details from my custom error page.
Error.aspx
protected void Page_Load(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null) ex = ex.GetBaseException();
litErrorMessage.Text = String.Format("<div class=\"error\">{0}</div>", ex.Message);
litErrorStackTrace.Text = String.Format("<b>Source:</b>\n{0}\n<b>Stack Trace:</b>\n{1}\n", ex.Source, ex.StackTrace);
}
else
{
litErrorStackTrace.Text = "No Exception information available.";
}
}
I also tried using
HttpException ex = (HttpException)HttpContext.Current.Server.GetLastError();, as seen in some examples, but that did not work.
I also tried all kinds of code in Global.asax -> Application_Error, but it turns out it was not necessary. After trying all kinds of code there, including storing session variables, Application_Error is now empty.

ASP.NET Custom Error Page for Web App that uses a Master Page

Reference KB306355: How to create custom error reporting pages in ASP.NET by using Visual C# .NET
I understand how to create a Custom Errors page. There are many examples of how to do it, like in the link above.
None of the examples I have found shows how to do what I am after.
I have a Web Application that uses a Master Page.
In my Master Page, I have a Label control used for errors that all pages will see:
<h4 id="bannerError"><asp:Label ID="lblError" runat="server" /></h4>
In the code behind on that Master Page, I have this:
public void Page_Error(object sender, EventArgs e) {
var err = Server.GetLastError().GetBaseException();
ErrorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
Server.ClearError();
}
public string ErrorMessage {
get { return lblError.Text; }
set {
LogError(value);
lblError.Text = value;
}
}
The ErrorMessage is a property. My other pages can easily access it, and I was easily able to edit out the part about writing the error to our server's database.
The Web.config page configuration (snippet):
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<customErrors defaultRedirect="Default.aspx" mode="On">
<error statusCode="403" redirect="Default.aspx" />
<error statusCode="404" redirect="Default.aspx" />
</customErrors>
</system.web>
</configuration>
How would I edit my files so that any errors that occur on any of my pages in my application (that derive from Master Page), simply show this basic information through the Master Page instead of redirecting the page to another URL?
I know the question was about how to get the MasterPage solution to work, but I think that using the application level Error event is the best way to make a catch-all error handler to forward to an error page.
You basclly need to handle the Application_Error in the Global.asax file. Here you can not only handle all page-level errors, but also application-level errors and HTTP errors of some types (if they can reach your application pipeline).
I think this is a better and more cetralized method. Adding MasterPage-level or BasePage-level error event handlers is also possible, but as a second layer.
Look here for a good example of doing this.
You won't be able to use controls to set the error message for unhandled Page level errors because no controls will be created (see this MS article). You could catch errors on the Page level and set the Master Page content like this:
protected override void OnError(EventArgs e) {
var err = Server.GetLastError().GetBaseException();
var errorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
((MyMasterPageClass)Master).ShowError(errorMessage);
Server.ClearError();
}
And then in the Master Page set the content directly:
public void ShowError(string message) {
Response.Write(string.Format("<h4 id=\"bannerError\">{0}</h4>", message));
}
But again, your Master Page wouldn't be rendering anyway, so it sort of defeats the purpose. If you really want to avoid the redirecting to an error page, you could load the content with ajax using something like jQuery.get(), and then display the results/errors as needed:
var request = $.get("www.mywebsite.com/Bugs2012.aspx");
request.done(function (data) {
$("#childContent").html(data);
});
request.fail(function (xhr, status, msg) {
var displayMsg = "Request could not be completed. ";
if (status === "error") {
switch (xhr.status) {
case 404:
displayMsg += "The content could not be found.";
break;
}
}
$("#bannerError").text(displayMsg);
});
I tried to create a jsfiddle, but it's a bit contrived because of the cross-domain ajax issues: js fiddle

Losing session data in ASP.NET

I moved an ASP.NET site running on a server with .NET 1.1 to another server running with .NET 2.0.
In one of the pages I have the following code to detect an expired session:
protected void Page_Init(object sender, System.EventArgs e) {
if ( Session["XBCPEmail"] == null ) {
Response.Redirect("signin.aspx?expired=yes");
return;
}
}
(Session["XBCPEmail"] == null) is resolving as true (as if the session had expired) in one unexpected case, after clicking one of the buttons of the page. It happens with only one of the buttons. Just like other buttons in the same page, the button event handler ends with this code redirecting to the same page:
Response.Redirect("cpanel.aspx");
I checked and at the time of Response.Redirect("cpanel.aspx"); the value of (string)Session["XBCPEmail"] is a valid string, so I'm not sure what can happen between the Response.Redirect and the Page_Init that could be making the Session["XBCPEmail"] become null.
Which could make a Session variable in .NET 2.0 become null? This code does not have that issue in 1.1 and, even in 2.0, it only affects one button on the page.
UPDATE: The issue only occurs if the button event handler calls an external .exe program, with the code below. If this code is commented out, the Session variable is not null. How can the creation of an external process to run a command line program have any impact on if a Session variable is null or not?
private string CallBridge3(string task, string arg1, string arg2, string arg3) {
Process process = new Process();
process.StartInfo.FileName = MapPath("bridgefcp.exe");
process.StartInfo.Arguments = "-" + task + " \"" + arg1 + "\" \"" + arg2 + "\" \"" + arg3 + "\"";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return output;
}
UPDATE 2: The problem has vanished after installing .NET 4.5 on the Windows 2008 R2 with IIS 7.5 machine, instead of using the one that came by default, which was .NET 2.0.
By default Response.Redirect terminates thread execution and there might be a race conditions in setting session variables. It is described in article Don't redirect after setting a Session variable (or do it right), so try to use another, less violent version:
Response.Redirect("cpanel.aspx", false);
Check your web.config, maybe you have this tag
<httpCookies requireSSL="true" />
If it so, remove it.
You need to update web.config as mention below :
<httpCookies requireSSL="false" />
I was facing the same issue and tried every option mentioned in the above answers.
Finally found that the issue was that we had marked session cookie as secure in our project but were running it with http
If the server has not been setup for SSL and you try to mark the cookie secure, a new session will be generated for each request.
So finally enabling back https fixed it for me.
I believe your session in the web.config is being reset (getting a new SessionID for each postback)
You could try to debug this by putting the SessionID somewhere on the page (for testing) with
HttpContext.Current.Session.SessionID
This did happen on one of my websites and all i had to do was go into IIS and resave the SessionState Panel
Just go to your web.config file and edit your sessionstate tag. Set requiressl to false from true.
I encountered this problem when setting the Session variable before a redirect. I had enableSessionState="ReadOnly" in Web.config. It happens because the session does not exists and the redirect happens before the client can set the session cookie.
My solution was to set a dummy Session variable in the previous page load (login page in my case).
protected void Page_Load(object sender, EventArgs e)
{
// Put this in master page or login page
Session["createSession"] = true; /* ensure there's a cookie for session */
}
<httpCookies requireSSL="false" />
Removing this from the local web.config worked for me. The issue was only happening when running the app locally.
Removed the setting from web.config
Added it to the web.staging.config and web.production.config
For MVC, make sure the web.config has below configuration.
<httpCookies httpOnlyCookies="true" requireSSL="false" />
in <system.web> section

Categories