Control.UniqueID different after cross-page postback - asp.net

I have a simple ASP.NET page with a MasterPage. Within the MasterPage, I have two login fields:
<input type="text" runat="server" id="txtUserName"/>
<input type="text" runat="server" id="txtPassword"/>
When the controls are rendered to the page, ASP.NET renders the following:
<input type="text" runat="server" id="ctl00_txtUserName" name="ctl00$txtUserName"/>
<input type="text" runat="server" id="ctl00_txtPassword" name="ctl00$txtPassword"/>
If I understand correctly, the name attribute corresponds to the UniqueID property of a control. However, when I'm debugging Page_Load and attempt to view the UniqueID of these fields, they have different values (ctl0$txtUserName and ctl0$txtPassword respectively)!
Note that this does not seem to be an issue on all pages using this MasterPage. Most of them work correctly and use ctl0$txtUserName and ctl0$txtPassword in both rendering and Page_Load.
Any idea what might cause ASP.NET to render a different UniqueID for a control than it uses in Page_Load?

I'm still not sure what was causing the generated UniqueIDs in the MasterPage to be different in Page_Load than when rendered to the page. However, I was able to get around the issue by storing the UniqueIDs of these fields in hidden fields. I was then able to access the values directly in the Request.Form collection.
In other words, I did this:
In the MasterPage -
<input type="text" runat="server" id="txtUserName"/>
<input type="text" runat="server" id="txtPassword"/>
<input type="hidden" id="txtUserNameUID" value="<%=txtUserName.UniqueID%>"/>
<input type="hidden" id="txtPasswordUID" value="<%=txtPassword.UniqueID%>"/>
During Page_Load of the child page -
string username = Request.Form[Request.Form["txtUserNameUID"]];
string password = Request.Form[Request.Form["txtPasswordUID"]];
Hope this helps anyone else struggling with UniqueID weirdness in ASP.NET!

Weird quirk I just became aware of: any wrapping controls that are runat server must also have IDs. For instance, if you have a panel around the control, i.e. whatever "ctl00" is, it must be assigned an ID. If it is not set, it will be allocated one and this can change.

Related

ASP.NET WebForms form not being posted - why?

Although I don't consider myself a web programmer, I've done a fair amount of web programming, so I'm almost embarrassed to ask what is wrong with the below code. There is something fundamental about ASP.NET that I must be missing.
I have two pages, source.aspx and destination.aspx:
source.aspx - html:
<body>
<form id="form1" action="destination.aspx" method="post" runat="server">
<input id="Text1" type="text" />
<input id="Text2" type="text" />
<input id="Checkbox1" type="checkbox" />
<input id="Submit1" type="submit" value="submit" />
</form>
</body>
destination.aspx - code behind:
protected void Page_Load(object sender, EventArgs e)
{
// Below variable gets assigned null.
string text1 = Request.Form["Text1"];
}
When I submit the source.aspx form, once it gets to the destination.aspx form, there is no information in the FORM variables. I thought that the forms 'runat="server" ' would ensure that I ended up in the ASP.NET page pipeline, and in fact I can step through this code. There are no POSTed form variables other than viewstate, and the PARAMs collection doesn't have anything corresponding to control data either, not even ones that would correspond to decorated control names. The question is, what is happening that is making my POSTed variables 'disappear', at least to the destination page?
I'm not looking for alternatives how to make this work (i.e. make the controls server controls with runat="server", etc). I can fix the problem. What I am trying to determine is 'what is it about ASP.NET that makes my controls not appear to be receivable by the destination page. Thanks - I thought that I understood HTTP pretty well, but there seems to be a little sleight of hand courtesy of ASP.NET that I'm not seeing.
You can remove the runat="server" off of your form tag since you want to opt out of what ASP.NET gives you with server controls. You are basically thinking correctly that this should work without needing all the ASP.NET page processing bits.
It's a small change you need to make - you need to use 'name' instead of 'id' on your input controls in order for them to appear in the Form collection. It's a subtle thing but I believe it's not exclusive to ASP.NET - the name attribute specifies what to associate the value with in the POST variable collection.
Consult HTML input - name vs. id for more information on id vs. name
Good luck
Request.Form uses name attribute from elements. So you should write name attributes to each of the html elements.
<body>
<form id="form1" action="destination.aspx" method="post" runat="server">
<input id="Text1" name="Text1" type="text" />
<input id="Text2" name="Text2" type="text" />
<input id="Checkbox1" name="Checkbox1" type="checkbox" />
<input id="Submit1" type="submit" value="submit" />
</form>
</body>

Is it possible to eliminate name mangling in ASP.NET?

I know I can eliminate ID mangling in ASP.NET 4.0, but can I also eliminate name mangling? This looks like the best I can do:
<input name="ctl00$body$txtName" type="text" id="txtName" />
Is that correct?
ASP.NET relies on name mangling to route posted form data to input controls in nested naming containers. The ways to avoid name mangling are:
Don't use nested naming containers such as master pages or user controls. Input controls that are placed directly on an .aspx page will have simple names.
Don't use the standard ASP.NET input controls. Instead, you could:
Put <input type="text" name="name" /> (without runat="server") in the .ascx/.aspx and access its value via Request.Form["name"].
Create a custom server control that does the same.
Ok, so here's the deal. I needed to change the values of form elements dynamically (server side), I need to keep the MasterPage, and I have panels on the page as well. There is no way around it.
What I have done instead, is use server side "yellow tags", and public variables:
HTML:
<input type='hidden' name='x_login' id='x_login' value="<%= x_login %>" />
Code:
Public x_login As String = "some value"
And to access the value after a postback:
Request.Form("x_login")
Thanks to Michael Liu's answer for the very last bit there. I've upvoted his answer just for that reason.

Adding custom attributes to asp.NET RadioButton control

I want to add a custom attribute to an asp.net RadioButton called Key which I'm using client-side for an ajax request.
What I'm finding is that my aspx markup which is the following:
<asp:RadioButton ID="rdoPost" GroupName=PreferredContactMethod" value="Post" onclick="DoStuff(this)" runat="server" />
gets rendered in the page as
<span Key="ContactMethod">
<input id="rdoPost" type="radio" name="PreferredContactMethod"" value="Post" onclick="DoStuff(this);" />
</span>
whereas I'd expected (and hoped) to get the following
<input id="rdoPost" type="radio" Key="ContactMethod" name="PreferredContactMethod"" value="Post" onclick="DoStuff(this);" />
I've tried the same thing with an asp TextBox control and it works exactly as I'd expect simply adding the Key="myKey" attribute to the <input type="text"/> element.
Is there a way around this with the standard RadioButton control, or will I have to inherit from the standard one to achieve the markup I'm wanting?
Also... (sorry to ask two questions at the same time), is adding non-standard attributes to html markup a bad idea anyway? Currently I'm using these attributes in JavaScript in the following way:
var key = rdoPost.Key;
I've found from the question/answer below that the easiest way to do this is via the code-behind using the InputAttributes property as follows:
rdoPost.InputAttributes.Add("class", "myCheckBoxClass");
Why does ASP.Net RadioButton and CheckBox render inside a Span?

Html control and asp.net web control

i would like to know what exactly the difference between Html control
and asp.net web control. why do we need these two types of controls?
i have placed one html input text ,html button and asp.net text box AND ASP.NET BUTTON on my web page
<input id="Text1" type="text" />
<input id="Button2" type="button" value="button" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
when i take view source, both are rendered similarly
<input id="Text1" type="text" />
<input id="Button2" type="button" value="button" />
<input name="TextBox1" type="text" id="TextBox1" />
<input type="submit" name="Button1" value="Button" id="Button1" />
what is the advantage of web control over html control.
I got some links in the internet,but not clear what exactly
they are used for.
http://www.extremeexperts.com/Net/FAQ/DiffBetweenServerandHTMLControls.aspx.
Could any one please explain the difference between these two controls.
First, if you drag an Html control from the Toolbox onto your design surface as in your example, the tag created does not include runat="server". That means it is native Html tag and not a .NET control. A native Html tag without the runat="server" has no server-side functionality. Thus, you could not set the value of the your "Text1" input tag in the code-behind.
Second, once you add the runat="server" to your Html input tag, you convert it from a native Html tag into a HtmlControl which derives from System.Web.UI.Control. Now the question could morph into the differences between something that derives from System.Web.UI.Control and System.Web.UI.WebControl. However, to specifically address your question, let's compare a standard input type="text" control to the TextBox control:
TextBox control can be access from the code-behind where an input control cannot (not easily) which also means that you can wireup server-side events for a TextBox control whereas you cannot with a standard Html control.
A TextBox control automatically saves its value using ViewState.
A TextBox control can be skinned using a Theme and .skin file whereas a native Html control cannot.
A TextBox can render as either an input type="text" control or a textarea depending on its TextMode property.
A TextBox control can participate in validation using validators.
Last but not least, the TextBox control can use control adapters to render differently in different browsers if required. See http://msdn.microsoft.com/en-us/magazine/cc163543.aspx.
Now, all that said, if you do not need any of WebControl capabilities, then using an native Html control is substantially leaner. In your example, you simply dragged two empty controls onto your design surface. If that is all you needed then using the .NET control would be overkill. However, as you start adding AutoComplete and server-side events and such, the full content, Javascript and all, of what gets to the Browser is much larger.
In short HTML controls don't persist their state while Postbacks. On the other hand ASP.Net control provides you to luxury to have their state saved while several Postbacks automatically. Different while using ASP.Net control instead of HTML element is:
<input type="hidden" name="__VIEWSTATE" value="dDwtNTI0ODU5MDE1Ozs+.................." />
This hidden field is auto generated by ASP.Net and it contains all you controls state in value attribute.
The server controls have a runat="server" attribute which enables you to provide server-side logic for these controls in the code-behind. You can also add this attribute to existing HTML controls to gain this same functionality.
The HTML controls are simple controls that correspond directly to HTML elements.
The ASP.NET Web Controls abstract the HTML elements, and generally provide more control over styling (though some would call this a bad thing).

Legacy html form in ASP .net application

I have an html page that I am converting over to an asp .net page. This page contained a form that accesses an external website that I have no control over. There is some sample code below:
<asp:Content ID="sample" ContentPlaceHolderID="body" Runat="Server">
<form name="Subscribe" method="post" action="http://anexternalwebsitehere.com/subscribe.asp">
<input type="text" name="email" size="45" maxlength="120" />
<input type="submit" name="submit" value="Subscribe" />
</form>
</asp:Content>
The form is more complicated than the example I have provided, but it gives a rough idea of what i need to convert over. Here are the problems I have encountered.
If I leave it as is:
When you click on the submit button you have a postback to the current page and not to the external page
If simply convert everything over to be asp form controls and change the postback url:
The id's become some convoluted "ctl00_body_ctl00" which the external page is not able to interpret.
Note: I do need the page to be an aspx page because I am using a master page for other content on the page.
Additional note: this is not Microsoft MVC.
What am I missing?
The issue was with nested forms as others have mentioned.
I was able to fix all my issues by simply doing the following:
Remove the extra form element i was adding.
Leave all controls as simply html controls, except for the submit button.
Replace the submit button with an asp .net button, and set the postback url.
The old code is as follows:
<asp:Content ID="sample" ContentPlaceHolderID="body" Runat="Server">
<form name="Subscribe" method="post" action="http://anexternalwebsitehere.com/subscribe.asp">
<input type="text" name="email" size="45" maxlength="120" />
<input type="submit" name="submit" value="Subscribe" />
</form>
</asp:Content>
The new code:
<asp:Content ID="sample" ContentPlaceHolderID="body" Runat="Server">
<input type="text" name="email" size="45" maxlength="120" />
<input type="submit" name="submit" value="Subscribe" />
<asp:button postbackurl="http://anexternalwebsitehere.com/subscribe.asp" text="Subscribe" runat="server" />
</asp:Content>
This fixes any of the issues with invalid nested forms as there are none. It also addresses the issue of asp .net renaming the asp elements because the only control that is being renamed is the asp button control which was not necessary for the submission to succeed.
Since you probably have the server form tag on your masterpage spanning your contentplaceholder, this new form you're declaring will be placed inside the server-form (by server-form i mean the one asp.net use for postbacks with runat="server")
I've had cases when i needed a special non-server form on an aspx page that already had a server-form, and the way i solved the problem was to place this non-server form outside the server-form - what i mean is, place it after the server-form. Since you use masterpages, you will need a new contentplaceholder on that masterpage, you can call it "noform". It is placed after the server-form so any content put in this noform will be placed outside the server-form. This mean no asp.net controls will work in this specific contentplaceholder (noform) since they won't be picked up by the framework, but you will be able to place your non-server form there and do your magic on that.
The problem, as you've probably guessed, is that you've got one form inside another form - ie the legacy form is appearing inside the ASP.NET form required by the master page.
One quick (if rather clunky) way to get around this is to close the ASP.NET form above the legacy form, and then open a new form below the legacy form. This means you've got three forms on the page, none of which are nested.
So you end up with something like this:
<asp:Content ID="sample" ContentPlaceHolderID="body" Runat="Server">
</form>
<form name="Subscribe" method="post" action="http://anexternalwebsitehere.com/subscribe.asp">
<input type="text" name="email" size="45" maxlength="120" />
<input type="submit" name="submit" value="Subscribe" />
</form>
<form method="post" action="myAspNetPage.aspx">
</asp:Content>
The closing </form> tag at the start closes the ASP.NET from the master page. You then have your form, which should now work as expected. Then the open <form> tag at the end simply ensures that the closing </form> tag from the master page is valid HTML.
Obviously anything appearing on the master page after the legacy form won't be within the standard ASP.NET form, so this may not work for you depending on how the rest of your page is structured.
It's not a particularly elegant solution, but it works as a quick fix (depending on what else is on your master page). We've used it where we had one legacy form required on a site with hundreds of pages, so we simply wanted a one-off fix rather than anything that affected the master page itself.
In our case, we couldn't change the legacy form as this was supplied by a third-party, regularly changed, and needed to be dropped into the ASP.NET page without a developer getting involved to amend it (eg as opposed to Brian's solution to his own question which requires editing the form and is clearly a better option in his case - and probably in most other cases where there is a similar problem).
Your button's click event will handle submission of the url and data.
//C# source
protected void button_Click(object sender, EventArgs e)
}
string customURL = "http://anexternalwebsitehere.com/";
string emailValue = textBoxEmail.Text; //of course validate this for proper email...
customURL += "page.aspx?email=" + emailValue;
Response.Redirect(customURL);
}

Resources