Textbox sending blank values to the server

I have the following HTML structure for my front end:

<p class="text-center" style="font-family: 'Playfair Display', serif; font-size: 1.25rem; font-weight: bold;">
    Sign Up
</p>

<div class="mb-3">
    <asp:TextBox ID="usernameInput" CssClass="form-control" PlaceHolder="Username" runat="server"></asp:TextBox>
</div>
<div class="mb-3">
    <asp:TextBox ID="emailInput" CssClass="form-control" PlaceHolder="Email Address" runat="server"></asp:TextBox>
</div>
<div class="mb-3">
    <asp:TextBox ID="passwordInput" CssClass="form-control" PlaceHolder="Password" runat="server"></asp:TextBox>
</div>
<div class="mb-3">
    <asp:TextBox ID="confirmPasswordInput" CssClass="form-control" PlaceHolder="Confirm Password" runat="server"></asp:TextBox>
</div>
<div class="mb-3 text-center text-danger">
    <asp:CompareValidator
        ID="passwordValidator"
        runat="server"
        ErrorMessage="Passwords do not match!"
        ControlToValidate="confirmPasswordInput"
        ControlToCompare="passwordInput"
        Operator="Equal"
        Type="String">
    </asp:CompareValidator>
</div>

<div class="d-grid">
    <asp:Button runat="server" ID="registerButton" Text="Sign Up" CssClass="Greengradiant btn-large" OnClick="registerButton_Click" UseSubmitBehavior="false" />
</div>

The following is the code for the backend:

protected void registerButton_Click(object sender, EventArgs e)
{
    Debug.WriteLine($"Username: {usernameInput.Text}, Email: {emailInput.Text}, Password: {passwordInput.Text}, Confirm Password: {confirmPasswordInput.Text}");

    Guid uniqueId = Guid.NewGuid();

    SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Database1"].ConnectionString);
    connection.Open();
    bool emailExists = false;

    using (SqlCommand command = new SqlCommand("SELECT COUNT(*) FROM [User] WHERE Email = @userEmail", connection))
    {
        command.Parameters.AddWithValue("@userEmail", emailInput.Text);
        emailExists = (int)command.ExecuteScalar() > 0;
    }

    if (emailExists)
    {
        Response.Write("<script>alert('Email is already in use!');</script>");
    }
    else
    {
        string insertStatement = "INSERT INTO [USER] (User_ID, Username, Email, Password, Role, Created_At) " +
            "VALUES (@userId, @username, @userEmail, @hashedPassword, @userRole, @creationDate)";

        SqlCommand insertCommand = new SqlCommand(insertStatement, connection);
        string hashedPass = Hash.ComputeHash(passwordInput.Text, "SHA512", null);
        insertCommand.Parameters.AddWithValue("@hashedPassword", hashedPass);
        insertCommand.Parameters.AddWithValue("@userId", uniqueId.ToString());
        insertCommand.Parameters.AddWithValue("@userEmail", emailInput.Text);
        insertCommand.Parameters.AddWithValue("@username", usernameInput.Text);
        insertCommand.Parameters.AddWithValue("@userRole", 0);
        insertCommand.Parameters.AddWithValue("@creationDate", DateTime.Now);

        insertCommand.ExecuteNonQuery();

        Response.Write("<script>alert('Account created successfully! Welcome!');</script>");
    }

    connection.Close();

    usernameInput.Text = "";
    emailInput.Text = "";
}

When I click the sign-up button, the data being sent to the server, such as usernameInput.Text, comes back empty.

That’s puzzling! Could caching issues be at play here? I’ve read sometimes disabling ViewState in asp controls can create such behavior. Maybe consider adding EnableViewState="true" to your TextBox controls. Curious if making manual debugging changes would reveal more. Have others faced this?