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
Related
Strange behavior occured in an old WebForms app. I can't give you link, or big picture, I can only ask for specific detail, so maybe someone has an idea which way to explore.
App on the domain A embeds app on another domain B within iframe. (If it hosts the site on the same domain, then it's fine, the problem doesn't occur.)
domainA.com:
<iframe src="http://domainB.com/page1.aspx" />
page1.aspx writes a Session variable:
http://domainB.com/page1.aspx:
HttpContext.Current.Session["UTCOffset"] = utcOffset.ToString();
However, ASHX handler handler.ashx within that iframe can't read the Session variable value.
http://domainB.com/handler.ashx:
string utcOffset = Convert.ToString(HttpContext.Current.Session["UTCOffset"]);
utcOffset is empty string.
Have in mind, when this is not inside iframe, (e.g. request http://domainB.com/page1.aspx through browser) this works fine.
It also works fine if this is all hosted on the same domain.
Also it was working fine until recently, on most major browsers.
Did something change recently regarding Session policy within frames, due to CORS or something?
How do I fix this?
I solved it simply by using cookies. Tested it, it works fine.
So instead of the code in page1.aspx:
HttpCookie UTCOffset = new HttpCookie("UTCOffset");
UTCOffset.Values.Add("utcOffset", utcOffset.ToString());
UTCOffset.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(UTCOffset);
and in handler, instead of current code:
string utcOffset = string.Empty;
HttpCookie UTCOffset = HttpContext.Current.Request.Cookies["UTCOffset"];
if (UTCOffset != null && !string.IsNullOrEmpty(UTCOffset.Values["utcOffset"]))
{
utcOffset = UTCOffset.Values["utcOffset"].ToString();
}
In my view I have something like the following
<img src="#Url.Action("GetImage", new {param1 = ViewBag.Param1, page = ViewBag.Page })" alt="" />
This works some of the time. However, every now and then the image just doesn't load. I set a breakpoint in the GetImage ActionResult and when the image isn't loading, the breakpoint isn't being hit.
This behavior seems to be completely random, if I just refresh the page over and over sometimes it works sometimes it doesn't. Any ideas or suggestions?
view :
<img src="#Url.Action("GetImage",new {name="google.png"})" alt="" />
and controller action look like below
[AcceptVerbs(HttpVerbs.Get)]
public FileResult GetImage(string name)
{
var path = #"C:\VS2015\Images\" + name;
return new FileStreamResult(new FileStream(path,FileMode.Open),"image/jpeg");
}
Hope your controller action code look like above.
it will work fine.
(Should be a comment but too long...)
Before you start diagnosing server-side issues, find out what the actual problem is.
Open up the browser developer tools (F12 on win), switch to the Network tab and keep refreshing until the problem occurs. (Note: there's a setting to disable the browser cache when dev tools are open, make sure to uncheck it to replicate the situation accurately)
When the problem occurs, scroll down to the request for the image and check if ti was fetched from the server or the local cache. If from the server, there should be a status code which will give you a hint (404/500) and the response body may contain useful information (like a full stack trace if your server is configured to show errors). At the very least, a server response means that a connection was made and that there should be some useful information in server logs.
It's also possible the problem is with either the browser cache or a proxy between the client and server.
Finally, if it is a problem server-side and you can't see error details in the browser, have a rummage through the servers event logs. All .Net errors are recorded there (by default at least).
Once you've got more information on what's causing the problem, edit your question and we can go from there.
I have an ASP.NET 4.0 WebForms application. I need to access HttpContext.Current.Session and set a value in the AcquireRequestState event (or an event after it) in Global.asax, and I've found a peculiar behavior.
Let's say I have a virtual directory in IIS (version 7 in my case) called Foo. In that I have Default.aspx as the home page. A sample Global.asax file is below:
<%# Application Language="C#" %>
<script runat="server">
void Application_AcquireRequestState(object sender, EventArgs e)
{
HttpContext.Current.Session["key"] = "value";
}
</script>
When I visit http://localhost/Foo/Default.aspx in my browser, it works just fine. When I visit http://localhost/Foo/ I get a NullReferenceException where I set the value on the session. The only change is the URL in the browser. They end up hitting the same page, but the framework behaves differently based on whether or not the URL contains just a folder name, or if it contains an aspx file.
Checking if (HttpContext.Current.Session != null) is not an option for me, because I need to set a value on the session with every request, which is non negotiable.
Is there a config setting in IIS that I'm missing, or is this a bug/forgotten feature?
An answer for another question hinted at the fact IIS does not load the session for every kind of request, for example style sheets don't need a session. Maybe this behavior is happening because IIS can't tell ahead of time if that folder name will result in executing an aspx file or if it will deliver a static HTML file?
Update: I even tried re-ordering the default documents that IIS looks for so that "default.aspx" was at the top of the list, e.g.
default.aspx
Default.asp
Default.htm
...
And I am still getting the same problem.
Update:
The event handler is only getting fired once because it is resulting in a NullReferenceException. I've done some additional reading and I know ASP.NET triggers these events for every request, even for CSS or JavaScript files. Additionally, the session object is not loaded for static files because there is not code that accesses the session, thus no need to load the object. Even so, the very first request is the request for the web page, which will need the session, and the session is null.
#DmytroShevchenko asked:
First add a guard check if (HttpContext.Current.Session != null) so that there is no NullReferenceException thrown. Then try to see, maybe the event will be fired a second time, with a session available.
Modified code:
void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session["key"] = "value";
}
}
I set a break point at the if statement. I saw this event fire 4 times:
session is null
session is null
session not null
session is null
When continuing to step through the code each time, only when it started executing Default.aspx and its code-behind did I have a session available. I actually had the web page open in Firefox and was monitoring the network requests. The first request was for http://localhost/Foo/.
Next I set a breakpoint in Application_BeginRequest as well and got the following events:
BeginRequest
AcquireRequestState
BeginRequest
AcquireRequestState
BeginRequest
AcquireRequestState (session is not null)
Execute Default.aspx (/Foo returns a response to the browser)
BeginRequest
AcquireRequestState (session is null again)
At #9 the AJAX request in the browser to http://localhost:54859/8fad4e71e57a4caebe1c6ed7af6f583a/arterySignalR/poll?transport=longPolling&connectionToken=...&messageId=...&requestUrl=http%3A%2F%2Flocalhost%2FFoo%2F&browserName=Firefox&userAgent=Mozilla%2F5.0+(Windows+NT+6.1%3B+WOW64%3B+rv%3A41.0)+Gecko%2F20100101+Firefox%2F41.0&tid=4&_=1445346977956 is hanging waiting for a response.
I found a discussion about the differences between serving a page by its explicit URL and serving a default document.
With MVC and WebAPI, a new HttpModule was introduced: ExtensionlessUrlHandler. I believe that your event firing multiple times (and only once with session being available) may be caused by this module or other (re)routing logic of ASP.NET that actually redirects ASP.NET to handle Default.aspx.
Also, as you yourself mentioned, these events can be triggered for static file requests.
The bottom line is, you should not rely on session being available every time your event is fired. But it is safe to assume that you can access session at least once when serving an ASP.NET page. Hence, this is how your code should look like:
void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session["key"] = "value";
}
}
What is happening is that certain events that occur prior to transferring the request to the page, trigger this event. Similarly, this event can be raised by other than ASPX pages. I think you need to do a few things:
set AutoEventWireUp to false in your page's code (in default.aspx). It seems odd and unrelated, but apparently this can resolve your issue.
check for null. Really. Because from all events, you are only interested in those events that originated from an ASPX page (or similar) that actually have a session state. Since every true request from a user always creates a session, you can simply filter for these without worrying that you miss certain events. As you have seen, at every cycle, there is always at least one event hit that has a set Session.
use PostAcquireRequestState, it is the more natural thing to use (or use PreRequestHandlerExecute), because on that event, all state is guaranteed to be set and filled.
I think your request url is not contain ".aspx", right?
The IIS7+ version has the config whitch will not use the "SessionStateModule" when it think the request handler is not managedHandler
So the solution is easy
Find your web.config, then add the property
<modules runAllManagedModulesForAllRequests="true">
....
</modules>
runAllManagedModulesForAllRequests="true" tell asp.net use all modules anyway
hope helpfull
When the resource has compilation error then the session will be null even in Application_PostAcquireRequestState
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
I've got some (badly written) legacy code that I have to modify but I'm having an odd problem with the prefixing of the controls.
The main page has several include files, including cpct_cost.aspx.
Within that included page is a control EquipmentCost:
<INPUT id="EquipmentCost" type="text" name="EquipmentCost" runat="server" size="10" onchange="TotalCost();" class="bk">
Another page references that control in client side javascript:
function TotalCost()
{
var a = document.CPCT_FORM.cpct_cost_EquipmentCost.value;
This is throwing a client error because when I run the code locally, the control is being named with a $ instead of an _:
<input name="cpct_cost$EquipmentCost" type="text" id="cpct_cost_EquipmentCost" size="10" onchange="TotalCost();" class="bk" />
And as a result, the client side javascript can't find the element in question.
The legacy code on the server handles this differently - the control name there is processed as:
<input name="cpct_cost:EquipmentCost" id="cpct_cost_EquipmentCost" type="text" size="10" onchange="TotalCost();" class="bk" />
and this is being processed correctly.
I thought at first it might be a local IIS setting, so I compiled my code and deployed it to the dev server, but the behavior was identical to my local execution.
I'm using what are supposed to be the latest source files, I haven't changed any project settings, so ... is there some way I can force the code from my machine to use the : instead of $? Or ... what am I missing?
The project is currently on the proposal list to be completely rearchitected, (so please, no suggestions to redesign the app ;) ) but in the mean time, I have a short term requirement to implement some minor new functionality in this ugly old beast, and I've got to get it done ASAP. What's frustrating is - I haven't changed these parts of the code at all, but the behavior is changing anyway.
UPDATE
Apparently the naming prefix used in at least .NET 1.1 is somewhat random, because after several builds, while I was trying various ways to work around this, the controls ended up getting the right name. So now I'm just not changing the code, which sucks because I really hate taking this "freeze it while it's randomly right" approach.
You could pass in a reference to the input control as a parameter to the JS function, ie:
<INPUT id="EquipmentCost" type="text" name="EquipmentCost" runat="server" size="10" onchange="TotalCost(this);" class="bk">
function TotalCost(txtEquipCost) {
var a = txtEquipCost.value;
}
Then it doesn't matter what the id is.
EDIT:
If you have more controls, create JS variables on the page, eg:
var txtEquipCost = document.getElementById('<%= YourControl.ClientID %>');
var txtOtherCost = document.getElementById('<%= YourOtherControl.ClientID %>');
Then the onChange function call could be TotalCost(txtEquipCost, txtOtherCost)
EDIT2:
See this question about ClientId and UniqueId which may be useful:
C# asp.net Why is there a difference between ClientID and UniqueID?
You could change your Javascript to use the id that is getting generated.
function TotalCost()
{
var a = document.getElementById('<%= YourControl.ClientID %>').value;
}
Also if you need absolute control over the generated id of that control it turns out that in asp.net 4.0 the ClientIDMode property was introduced so that developers have more control over how that id is generated.
Check out these two sources
http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientid.aspx
http://weblogs.asp.net/asptest/archive/2009/01/06/asp-net-4-0-clientid-overview.aspx