40

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/ (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(&quot;ctl00$ContentPlaceHolder1$continueImageButton&quot;, 
&quot;&quot;, true, &quot;continue&quot;, &quot;&quot;, 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...
Lieven Cardoen
  • 25,140
  • 52
  • 153
  • 244
  • Can you provide the code for your default.aspx file , the fact that the postback doesnt work is that the file is beiing redirect with a head request instead of a get or post request . that's why it doesn't work. – Flob Aug 29 '11 at 09:42
  • Done. If I look in Charles (http sniffer), I can see that a POST is being sent to the server. – Lieven Cardoen Aug 29 '11 at 09:52
  • When you say your postback "doesn't work", what exactly do you mean? You might want to put some breakpoints in your codebehind and run with the debugger to see exactly what is happening. – patmortech Aug 29 '11 at 10:39
  • You might include your codebehind for the page if you are having problems with something not running as expected there. – patmortech Aug 29 '11 at 10:40
  • Let's just say that the ContinueImageButton_Click is never triggered. Instead, the Page_Load is triggered everytime and not as a Postback. – Lieven Cardoen Aug 29 '11 at 10:56
  • 1
    Just to see if it makes a difference, put CausesValidation="false" on your button and see if it changes anything. – patmortech Aug 29 '11 at 11:28
  • Doesn't change a thing. Quite strange behavior, don't you think? I could redirect the call to default.aspx, but I would really like to know why this is happening. – Lieven Cardoen Aug 29 '11 at 12:24
  • @Lieven Cardoen: are you using update pannel here?? – Chamika Sandamal Sep 04 '11 at 09:45
  • slfan is absolutely right. I was running into that issue. Seemed weird since IIS isn't supposed to be case sensitive. But for the default page, it apparently is. Once I changed that (disable then delete the old, add new and enable) and cleared the cache from my browser, it worked like a charm. Using IIS 7.5. –  Sep 08 '11 at 20:38
  • interesting for me... i had this problem, it existed only on the server. But I could always launch locally (dev box) and use just http:/localhost/. I had the issue where i was constantly getting httpHostx64.exe stopped working. I used this fix... https://thomas-barthelemy.github.io/2015/05/01/visual-studio-vshub/ and suddenly i started getting the issue on my local box as well. @Eric's answer solved it in both places. – greg Oct 13 '16 at 17:26

9 Answers9

51

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>
Michel Ayres
  • 5,891
  • 10
  • 63
  • 97
TheCodeKing
  • 19,064
  • 3
  • 47
  • 70
  • In my case, the problem was a FluorineFx HTTP Module (.NET Amf Remote Gateway). If I add preCondition="managedHandler" to the configuration of the module in web.config, everything works fine. However, FluorineFx does also deal with static content, so if you want this to keep on working, it's best to manually set the Action attribute on the Form. – Lieven Cardoen Sep 10 '11 at 12:49
  • 2
    This is great, but is there any way to configure IIS to fix it, instead of having to make code changes? Smells like an IIS bug to me or just poor design by MS. – Craig Feb 07 '12 at 11:19
  • Also, if you're not using the form at the Master Page level, and you are using it only on several pages, including the default one, you can set the action
    – Adrian Iftode Sep 20 '13 at 12:14
  • 1
    What if the wrapping form tag is in Site.master but every sub-page handles their own requests? While I'm on Users.aspx page I don't want to send requests to Default.aspx... – yosh Oct 03 '14 at 10:19
  • 4 hours fighting this one today until I found your answer... thanks! – mxmissile Apr 25 '22 at 18:27
16

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";
    }
Eric
  • 161
  • 1
  • 2
  • Don't forget to append the query string if using the above, otherwise things like returnurl won't work. this.Page.Form.Action = "default.aspx" + Page.Request.QueryString; – Steven Quick Sep 18 '13 at 00:32
  • 1
    My previous comment is missing the ? for the query string, so: this.Page.Form.Action = "default.aspx?" + Page.Request.QueryString.ToString(); – Steven Quick Sep 18 '13 at 00:51
  • if the QueryString was specified - then the Form.Action won't be NullorEmpty – Mark A Jones Aug 07 '14 at 15:55
  • 1
    Private Sub Page_PreRender(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.PreRender If String.IsNullOrEmpty(Page.Form.Action) OrElse Page.Form.Action.StartsWith("?") Then If Page.Request.QueryString.Count = 0 Then Page.Form.Action = "Default.aspx" Else Page.Form.Action = "Default.aspx?" & Page.Request.QueryString.ToString() End If End If End Sub – Mark A Jones Aug 07 '14 at 15:57
  • wow I suck at formatting code in comments - sorry - I like this solution since there is only one default page per folder, make the page fix itself – Mark A Jones Aug 07 '14 at 16:03
  • 1
    If you're using FriendlyUrls this will break other pages like /search (which work fine), so I added a second test to make sure it's only on the default page: if (string.IsNullOrEmpty(this.Page.Form.Action) && Request.Url.AbsolutePath == "/default.aspx") this.Page.Form.Action = "Default.aspx"; – FirstDivision Aug 21 '14 at 19:09
  • Thanks @FirstDivision - I've actually used ` && Request.Url.AbsolutePath.ToLower().EndsWith("/default.aspx")` in my master page codebehind instead so it should fix all default document requests. – Ian Grainger Mar 16 '15 at 11:56
7

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);
    }
}
Waqas
  • 6,812
  • 2
  • 33
  • 50
  • 1
    Bravo this seems to be the solution, you might want to paste the code also here in your answer to have it a bit more complete than just give a link. – Davide Piras Sep 04 '11 at 10:18
  • 2
    This is a nice workaround, but what you are seeing isn't normal behavior IMO, it should just work. Your environment is messed up or there are some other factors at work. – TheCodeKing Sep 05 '11 at 12:28
1

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.

dougajmcdonald
  • 19,231
  • 12
  • 56
  • 89
0

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?

Hoyacoder
  • 41
  • 1
  • 3
0

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.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
vividsoup
  • 31
  • 2
0

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).

OrizG
  • 86
  • 7
  • 1
    No this doesn't work. The element looking like
    seems to be the problem - so it won't even try to postback correctly. Nice idea, though.
    – Ian Grainger Mar 16 '15 at 11:28
0

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.

Luminous
  • 1,771
  • 2
  • 24
  • 43
0

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.

slfan
  • 8,950
  • 115
  • 65
  • 78
  • Tried it, but doesn't change a thing, slfan. – Lieven Cardoen Sep 10 '11 at 08:58
  • I tried this too - definitely doesn't work. You're in danger of downvotes! ;) – Ian Grainger Mar 16 '15 at 11:31
  • @IanGrainger: it will work, if it is the cause of the problem, but of course not when the action tag is empty. When I wrote my answer I didn't know that the action tag was actually empty. – slfan Mar 16 '15 at 11:41
  • @slfan: I'm surprised this fixes anything on Windows anyway. My form action is already "default.aspx" - but the page is called Default.aspx (the default document rule entry is also "default.aspx") and it works fine. Apart from where it doesn't because the action is blank :) – Ian Grainger Mar 16 '15 at 11:58
  • It wasn't a Windows problem, the problem was in a library I used. The code compared "Default.aspx" with the current page and the comparison was case sensitive. – slfan Mar 16 '15 at 12:25