Get and set an ASP.NET TextBox value with JavaScript
An ASP.NET TextBox is a server control, but the browser never sees it as one. It sees an ordinary <input> (or a <textarea>), and reading or writing its text from JavaScript is a single property. The only real difficulty is finding the element, because the id in the page is not always the ID you typed in the markup.
What the browser receives
Take this control in a content page that uses a master page:
<asp:TextBox ID="txtCity" runat="server" Text="Lyon" />
Depending on the configuration, the rendered HTML looks like one of these lines:
<!-- ClientIDMode="AutoID" (the .NET 3.5 behaviour) -->
<input name="ctl00$MainContent$txtCity" type="text" value="Lyon" id="ctl00_MainContent_txtCity" />
<!-- ClientIDMode="Predictable" (the default for pages since .NET 4) -->
<input name="ctl00$MainContent$txtCity" type="text" value="Lyon" id="MainContent_txtCity" />
<!-- ClientIDMode="Static" -->
<input name="ctl00$MainContent$txtCity" type="text" value="Lyon" id="txtCity" />
The name attribute keeps the full naming-container path in every mode, because the server uses it to match posted values to controls. Only the id changes. That is why document.getElementById("txtCity") works on one project and returns null on another.
Three reliable ways to find the element
1. Emit the ClientID into the script
Inside an .aspx or .ascx file, a code expression writes the rendered id for you, whatever the mode:
<script>
var box = document.getElementById("<%= txtCity.ClientID %>");
</script>
This only works in markup processed by ASP.NET. A separate .js file is served as a static file, so the <%= %> block would reach the browser literally. Pass the id to the external script instead, for example through a data- attribute or a small inline variable.
2. Fix the id with ClientIDMode="Static"
<asp:TextBox ID="txtCity" runat="server" ClientIDMode="Static" />
Now the id is exactly txtCity. It is the simplest option for controls that appear once on a page. Avoid it inside a Repeater, GridView template or a user control that may be placed twice: every row would render the same id, and duplicate ids make getElementById return only the first match.
3. Select by something other than the id
A CSS class or a data attribute is not rewritten by ASP.NET:
<asp:TextBox ID="txtCity" runat="server" CssClass="js-city" />
<script>
var box = document.querySelector(".js-city");
</script>
Reading the value
Once you have the element, the current text is in its value property. Use the property, not getAttribute("value"): the attribute holds the value the page was rendered with, while the property follows what the user has typed since.
var box = document.getElementById("<%= txtCity.ClientID %>");
var city = box.value; // what is in the box right now
var original = box.defaultValue; // the value sent by the server
if (city.trim() === "") {
alert("Please enter a city.");
}
Setting the value
Assigning to the same property changes the text immediately:
box.value = "Marseille";
box.focus();
box.select(); // optional: highlight the new text
Setting value from script does not raise the input or change events. If other code listens for them, raise one yourself:
box.value = "Marseille";
box.dispatchEvent(new Event("change", { bubbles: true }));
With AutoPostBack="true", ASP.NET renders an onchange attribute that calls __doPostBack. Dispatching a change event runs that handler, so the page posts back as if the user had edited the field.
A complete page
The following Web Forms page (C# code-behind, .NET Framework 4.8) copies a first name and a last name into a third box on the client, then shows on the server what was posted.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FullName.aspx.cs" Inherits="Demo.FullName" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Full name</title>
</head>
<body>
<form id="form1" runat="server">
<p>
<asp:Label runat="server" AssociatedControlID="txtFirst" Text="First name" />
<asp:TextBox ID="txtFirst" runat="server" />
</p>
<p>
<asp:Label runat="server" AssociatedControlID="txtLast" Text="Last name" />
<asp:TextBox ID="txtLast" runat="server" />
</p>
<p>
<asp:Label runat="server" AssociatedControlID="txtFull" Text="Full name" />
<asp:TextBox ID="txtFull" runat="server" />
</p>
<p>
<button type="button" onclick="buildFullName()">Combine on the client</button>
<asp:Button ID="btnSave" runat="server" Text="Post to the server" OnClick="btnSave_Click" />
</p>
<asp:Label ID="lblResult" runat="server" />
</form>
<script>
function buildFullName() {
var first = document.getElementById("<%= txtFirst.ClientID %>").value.trim();
var last = document.getElementById("<%= txtLast.ClientID %>").value.trim();
document.getElementById("<%= txtFull.ClientID %>").value = (first + " " + last).trim();
}
</script>
</body>
</html>
using System;
using System.Web;
using System.Web.UI;
namespace Demo
{
public partial class FullName : Page
{
protected void btnSave_Click(object sender, EventArgs e)
{
// The value typed or set in the browser is posted with the form.
lblResult.Text = "Server received: " + HttpUtility.HtmlEncode(txtFull.Text);
}
}
}
Note the plain <button type="button">. An <asp:Button> renders a submit button, so clicking it would post the form before you could see the client-side result. If you want an asp:Button to run script only, use OnClientClick="buildFullName(); return false;".
The HtmlEncode call matters: the label writes raw HTML, and the text came from the user.
What the server sees after a postback
A TextBox reads its new text from the posted form data, so a value changed by JavaScript reaches txtFull.Text exactly like a value typed by the user. Two exceptions catch people out.
ReadOnly="true"
The browser does post a read-only box, but ASP.NET deliberately ignores the posted text for a TextBox whose ReadOnly property is true; it keeps the value from view state. This stops a user from tampering with a field the server considers locked. If you fill a read-only-looking box from script and need the value on the server, set the HTML attribute instead of the property:
protected void Page_Load(object sender, EventArgs e)
{
// Read-only in the browser, but the posted value is still processed.
txtFull.Attributes["readonly"] = "readonly";
}
Validate that value on the server like any other input: making a box read-only in HTML protects nothing.
Disabled boxes
A disabled form field is never submitted; that is a rule of HTML forms, not of ASP.NET. If you disable a box with box.disabled = true after filling it, its value is lost on postback and the control falls back to its previous text. Use readOnly on the client if the value must travel.
Multiline boxes and passwords
TextMode="MultiLine"renders a<textarea>. Thevalueproperty works the same way; line breaks arrive as\nin the browser and are posted as\r\n.TextMode="Password"never writes itsTextback into the rendered page, so after a postback the box is empty even thoughvaluewas set before submitting. That is intended behaviour.MaxLengthbecomes amaxlengthattribute, which limits typing but not script.box.value = "a very long string"is accepted, so check lengths on the server as well.
Common errors
| Symptom | Likely cause |
|---|---|
Cannot read properties of null (reading 'value') | The id is wrong (naming container prefix) or the script runs before the element exists. Put the script after the form or wrap it in a DOMContentLoaded handler. |
| Text set by script disappears after clicking a button | The box was disabled, or it has ReadOnly="true" on the server. |
<%= txtCity.ClientID %> appears literally in the browser | The code is in an external .js file, which ASP.NET does not process. |
| "The Controls collection cannot be modified because the control contains code blocks" | A <%= %> block sits inside a <head runat="server"> whose controls are changed in code. Move the script to the body, or use a data-binding expression <%# %> with Page.Header.DataBind(). |
The same task with jQuery is covered in Get and set a TextBox value with jQuery, and turning a box on and off is in Enable or disable a TextBox on a button click.
Official documentation
- Microsoft Learn: TextBox class and TextBox.ReadOnly property
- Microsoft Learn: Control.ClientID and ClientIDMode enumeration
- MDN: Document.getElementById(), HTMLInputElement and dispatchEvent()