Postback doesn't work with aspx page as Default Document
If I browse to http://localhost/edumatic3/trunk/login/accesscode/Default.aspx, my postback works. However, if I browse to http://localhost/edumatic3/trunk/login/accesscode/开发者_如何学JAVA (with Default.aspx defined as default document), my postback doesn't work.
Is there a way to make this work? Or should I remove the default document and force users to browse to http://localhost/edumatic3/trunk/login/accesscode/default.aspx?
UPDATE:
Code (part):
<div id="continueDiv">
<asp:ImageButton ID="continueImageButton"
runat="server" ValidationGroup="continue"
OnClick="ContinueImageButton_Click"
AlternateText="<%$ Resources:login, continue_alternatetext %>"/>
</div>
Code behind (part):
protected void Page_Load(object sender, EventArgs e)
{
Log.Debug("Page_Load(...)");
Log.Debug("Page_Load(...) :: PostBack = " + IsPostBack);
if (!IsPostBack)
{
continueImageButton.ImageUrl = "~/App_Themes/" + base.Theme
+ "/images/" + Resources.login.btn_continue;
}
}
/// <summary>
/// Continue Image Button Click Handler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ContinueImageButton_Click(object sender, EventArgs e)
{
....
When I click on the ImageButton, Page_Load is triggered, and IsPostBack is false... Normally, it should be true. ContinueImageButton_Click(...) isn't triggered at all.
In HTML (part):
<input type="image" name="ctl00$ContentPlaceHolder1$continueImageButton"
id="ctl00_ContentPlaceHolder1_continueImageButton"
src="../../App_Themes/LoginTedu/images/en_continue.png" alt="Continue"
onclick="javascript:WebForm_DoPostBackWithOptions(new
WebForm_PostBackOptions("ctl00$ContentPlaceHolder1$continueImageButton",
"", true, "continue", "", false, false))"
style="border-width:0px;">
Http request:
POST /edumatic3/trunk/login/accesscode/ HTTP/1.1
Host: localhost
Referer: http://localhost/edumatic3/trunk/login/accesscode/
Content-Length: 1351
Cache-Control: max-age=0
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1
(KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: nl,en-US;q=0.8,en;q=0.6,fr;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
ASP.NET_SessionId=33yal3buv310y2etuj33qghg; CurrenUICulture=en-us
__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDw...
I thought I'd try and reproduce this, and you're absolutely right. It breaks without the default.aspx
with a very simple example that you provided. Looking at the HTML, the reason is fairly clear. It's because the action attribute is empty.
A quick search reveled this, ASP.NET 4 Breaking Changes (see Event Handlers Might Not Be Not Raised in a Default Document in IIS 7 or IIS 7.5 Integrated Mode).
ASP.NET 4 now renders the HTML form element’s action attribute value as an empty string when a request is made to an extensionless URL that has a default document mapped to it. For example, in earlier releases of ASP.NET, a request to http://contoso.com would result in a request to Default.aspx. In that document, the opening form tag would be rendered as in the following example:
<form action="Default.aspx" />
In ASP.NET 4, a request to http://contoso.com also results in a request to Default.aspx. However, ASP.NET now renders the HTML opening form tag as in the following example:
<form action="" />
This difference in how the action attribute is rendered can cause subtle changes in how a form post is processed by IIS and ASP.NET. When the action attribute is an empty string, the IIS DefaultDocumentModule object will create a child request to Default.aspx. Under most conditions, this child request is transparent to application code, and the Default.aspx page runs normally.
However, a potential interaction between managed code and IIS 7 or IIS 7.5 Integrated mode can cause managed .aspx pages to stop working properly during the child request.
I've created these two fixes which resolve the issue, use either.
1) Add this code to Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if (app.Context.Request.Url.LocalPath.EndsWith("/"))
{
app.Context.RewritePath(
string.Concat(app.Context.Request.Url.LocalPath, "default.aspx"));
}
}
2) Create a Forms ControlAdapter
public class FormControlAdapter : ControlAdapter
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
base.Render(new RewriteFormHtmlTextWriter(writer));
}
public class RewriteFormHtmlTextWriter : HtmlTextWriter
{
public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
: base(writer)
{
this.InnerWriter = writer.InnerWriter;
}
public override void WriteAttribute(string name, string value,
bool fEncode)
{
if (name.Equals("action") && string.IsNullOrEmpty(value))
{
value = "default.aspx";
}
base.WriteAttribute(name, value, fEncode);
}
}
}
Register it by creating this file in App_Browsers\Default.browsers
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
adapterType="TheCodeKing.Web.FormControlAdapter" />
</controlAdapters>
</browser>
</browsers>
Another option, is to check if the form action is empty right before rendering the page. This worked for me:
public void Page_PreRender(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.Page.Form.Action))
this.Page.Form.Action = "Default.aspx";
}
If you are interested in adding some extra code in your default.aspx file, then you can use the similar approach defined in blog post here; Which is about redirecting the user to same default page but with explicit page name....
//code, copied from mentioned blog
protected void Page_Load(object sender, EventArgs e)
{
string defaultPage = "default.aspx";
string rawUrl = Request.RawUrl; //get current url
//if current url doesn't contains default page name then add
//default page name, and append query string as it is, if any
if (rawUrl.ToLower().IndexOf(defaultPage) < 0)
{
string newUrl;
if (rawUrl.IndexOf("?") >= 0)
{
// URL contains query string
string[] urlParts = rawUrl.Split("?".ToCharArray(), 2);
newUrl = urlParts[0] + defaultPage + "?" + urlParts[1];
}
else
{
newUrl = (rawUrl.EndsWith("/")) ? rawUrl + defaultPage : rawUrl + "/" + defaultPage;
}
Response.Redirect(newUrl);
}
}
Have you tried setting your image button to use the Command event rather than 'Click'?
I think it 'could' be possible that an image click doesn't cause a full postback, perhaps try defining things as below:
void ImageButton_Command(object sender, CommandEventArgs e)
{
if (e.CommandName == "YourCommandName")
//do your action
}
Then define your button like this:
<asp:ImageButton id="btn1" runat="server"
ImageUrl="images/image.jpg"
OnCommand="ImageButton_Command"
CommandName="YourCommandName"/>
I seem to remember needing to do this to allow an image button to 'submit' a form, so I presume this will cause the postback you're after.
I once had a similar problem. The problem was that in IIS the default document was configured as default.aspx, but the name of my page was Default.aspx. It was just a matter of case sensitivity.
When I upgraded my web project from VS 2005 (.Net 2.5) to VS2010 (.Net 4.0), the following was inserted by VS2010 into my web.config:
<system.webServer>
<defaultDocument>
<files>
<add value="mydefaultpage.aspx" />
</files>
</defaultDocument>
</system.webServer>
When I navigated to "http://myserver/mywebsite", which I was formerly able to do under .Net 2.5, I got
"HTTP Error 500.19 - Internal Server Error "The requested page cannot be accessed because the related configuration data for the page is invalid." (It displayed the "defaultDocument" node.)
However, I was able to fix the problem very simply in web.config simply by inserting "/" at the beginning of the default web page value, as shown below:
<system.webServer>
<defaultDocument>
<files>
<add value="/mydefaultpage.aspx" />
</files>
</defaultDocument>
</system.webServer>
I didn't have to do any of the other things suggested by the other respondents.
Are there any unintended consequences or gotchas from doing it this way?
If your form processor action is not in the root you should be able to use an absolute path without using the file name.
<form action='/form/processor/' method=post id='myform'>
Tested in .NET 2.0
The issue occurred with blank action path, but worked correctly with path entry.
Consider using URL Mappings done through your web.config. That way you can avoid extra code in your app and let IIS work for you.
<system.web>
<urlMappings>
<add url="~/login" mappedUrl="~/login/default.aspx" />
<add url="~/login/" mappedUrl="~/login/default.aspx" />
<add url="~/this-folder-does-not-exist" mappedUrl="~/login/default.aspx" />
<add url="~/this-folder-does-not-exist/" mappedUrl="~/login/default.aspx" />
</urlMappings>
</system.web>
Make sure to include both versions of that URL with and without ending slash.
You can also create redirections from virtual folders when you need quick changes and don't want to modify the source code (as shown above with 'this-folder-does-not-exist' example).
This showed up for me after I incorporated Owin authentication using Azure B2C for the provider. The redirect uri I defined was to go back to the home page without it being /default.aspx or /Default.aspx. That caused the form post back to be blank. Expanding upon a similar answer here I got it to work with this.
public void Page_PreRender(object sender, EventArgs e)
{
var absolutePath = Request.Url.AbsolutePath;
if(string.IsNullOrEmpty(this.Page.Form.Action) && (absolutePath == "/default.aspx" || absolutePath == "/Default"))
this.Page.Form.Action = "Default.aspx";
}
I'll probably have to update this after I include FriendlyUrls, but that's okay.
精彩评论