Postback doesn’t work with aspx page as Default Document

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("https://stackoverflow.com/"))
    {
    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>

Leave a Comment