Call a JavaScript function from code-behind in ASP.NET (C#)
Server code cannot call a browser function directly: by the time the browser runs any script, the server has finished. What the server can do is write a script into the response that calls the function when the page loads. Web Forms has two helpers for that, and the important detail is encoding the values you pass.
Full postback: ClientScript.RegisterStartupScript
<script>
function showSaved(name, count) {
document.getElementById("status").textContent = name + " saved (" + count + " items).";
}
</script>
<p id="status" role="status"></p>
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" />
protected void btnSave_Click(object sender, EventArgs e)
{
string name = txtListName.Text;
int count = SaveList();
var json = new System.Web.Script.Serialization.JavaScriptSerializer();
string script = "showSaved(" + json.Serialize(name) + ", " + count + ");";
ClientScript.RegisterStartupScript(GetType(), "saved", script, true);
}
- The script is emitted just before the closing
</form>tag, so the elements of the form exist when it runs. - The key (
"saved") prevents the same script being registered twice in one response. trueas the last argument wraps the code in<script>tags.JavaScriptSerializer.Serializeturns the string into a JavaScript string literal with quotes, backslashes and line breaks escaped. Never concatenate raw user text into script, e.g."showSaved('" + name + "')": a name containing a quote breaks the script, and a malicious one injects code.HttpUtility.JavaScriptStringEncode(name, true)is an equivalent option.
Inside an UpdatePanel: ScriptManager.RegisterStartupScript
After an asynchronous postback, scripts registered through ClientScript are not executed, because only the panel's HTML is updated. Register through the ScriptManager with the control that caused the update:
ScriptManager.RegisterStartupScript(btnSave, btnSave.GetType(), "saved", script, true);
This overload works for full and partial postbacks, so code that might run in both situations can always use it (the page needs a ScriptManager).
A cleaner alternative: render data, let the script react
Generated script is hard to test and conflicts with a Content Security Policy that blocks inline scripts. Rendering a value and letting a static script read it avoids both:
<asp:Panel ID="pnlNotice" runat="server" CssClass="notice" Visible="false" data-autohide="5000">
<asp:Literal ID="litNotice" runat="server" Mode="Encode" />
</asp:Panel>
litNotice.Text = name + " saved."; // Mode="Encode" HTML-encodes it
pnlNotice.Visible = true;
// site.js, loaded on every page
document.querySelectorAll("[data-autohide]").forEach(function (el) {
setTimeout(function () { el.hidden = true; }, Number(el.dataset.autohide));
});
Alerts and confirmations from the server have their own articles: Show an alert from code-behind and Show a confirm box. Calling the server from script is the reverse direction: Call a server-side method with jQuery AJAX.
Official documentation
- Microsoft Learn: ClientScriptManager.RegisterStartupScript, ScriptManager.RegisterStartupScript
- Microsoft Learn: HttpUtility.JavaScriptStringEncode