Tag Archives: ASP.NET

Quick Tip: Use JQuery to submit a TextBox.

imageSubmitting a search box when <Enter> is pressed is a nice usability feature to provide.  Unfortunately, ASP.NET Web Forms and its requirement for a single <form> tag breaks this expected behavior when there is more than one submit button on the page.   This can be easily fixed with a JavaScript and JQuery.   Listening to the keydown event on the TextBox the Go submit button can be triggered when <Enter> is pressed.

jQuery("#searchTextBox").keydown(function (event) {
    if (event.keyCode && event.keyCode == '13') {
        jQuery("#searchButton").click();
        return false;
    } else {
        return true;
    }
});

Invoke an action between ASP.Net pages. Create a simple REST API for an ASP.NET page

Update March 1, 2013 I didn’t have a full understanding of a REST service at the time I wrote this post. I have a better understanding now and recommend using ASP.NET Web API

I needed a simple way for one page to call an action in another page.  In the spirit of a RESTful API I wanted that interaction to be called through a simple URL. 

http://localhost/Default.aspx?action=save

I initially started using a switch statement to handle the action passed in on the QueryString, but really wasn’t happy with the result.  I wasn’t interested in having to maintain a switch statement for the actions.  My first pass looked like this:

protected string Action { get; set; }

protected override void OnInit(EventArgs e)
{
    Action = Request.QueryString["action"] ?? string.Empty;
    base.OnInit(e);
}

protected void Page_Load(object sender, EventArgs e)
{
    switch (Action)
    {
        "Save":
            SaveAction();
            break;
        "Load":
            LoadAction();
            break;
        default:
            break;
    }
}

private void SaveAction()
{
    Response.Write("Save action called.");
}

private void LoadAction()
{
    Response.Write("Load action called.");
}

I decided to break out the handling of the action into a base class called ActionPage and use a event model to call the actions methods.  Following this refactoring the code behind was much easier to follow.

public partial class _Default : ActionPage
{
    protected void Page_Load(object sender, EventArgs e)
    { }

    protected override void RegisterActions()
    {
        PageActions.Add("save", SaveAction);
        PageActions.Add("load", LoadAction);
    }

    private void SaveAction()
    {
        Response.Write("Save action called.");
    }
    private void LoadAction()
    {
        Response.Write("Load action called.");
    }
}

The key was creating a ‘PageAction’ delegate that could be registered for each possible page action.  The RegisterActions method shows the action methods being registered using the PageAction delegate.  The page is now only responsible for performing the actions and no longer has to determine what action to call.   The work of reading the action from the QueryString and calling the action have been placed into the ActionPage base class.

public class ActionPage  : System.Web.UI.Page
{
    protected delegate void PageAction();
    protected readonly IDictionary<string, PageAction> PageActions = new Dictionary<string, PageAction>();
    protected string Action { get; set; }

    public ActionPage()
    {
        RegisterActions();
    }

    protected virtual void RegisterActions()
    {
    }

    protected void HandleAction(string action)
    {
        if (PageActions.ContainsKey(action))
            PageActions[action]();
    }

    protected override void OnInit(EventArgs e)
    {
        Action = Request.QueryString["action"] ?? string.Empty;
        base.OnInit(e);
    }
    protected override void OnLoad(EventArgs e)
    {
        HandleAction(Action);
        base.OnLoad(e);
    }
}

The ActionPage starts by calling RegisterActions in the constructor.  Register actions is the pages chance to register actions with the ActionPage.  The actions is then pulled from the QueryString it the OnInit method.  Then in OnLoad the action matching the one passed on the query string is called.  In this model if an invalid action is called nothing happens and the page renders normally.

SimpleRESTAPI_SampleSource.zip

JavaScript Variable Pattern

To help make writing and maintaining JavaScript easier in ASP.NET I have started to use a pattern that isolates the JavaScript variables away from the core script.  By doing this I can avoid a bunch of string concatenation in my server side code and embedded code blocks in my .aspx page when rendering dynamic JavaScript.  The core JavaScript can be placed into a .js file.  The ASP.NET page is now only responsible for rendering a list of updated variables that the core script expects.

To demonstrate consider a set of jQuery tabs that contains forms on each tab.  When a form is submitted from a particular tab the tab should be selected after the form posts back.  Using embedded code blocks the JavaScript would be. 

<script type="text/javascript">
    jQuery(function($) {
        $("#tabs").tabs();
        $("#tabs").tabs('select', <%=selectedTab %>);
    });
</script>

While this looks pretty clean it prevents us from putting this JavaScript into a .js file.  Applying the variable pattern the JavaScript can be refactored to the following and placed into a .js file.

jQuery(function($) {
    $("#tabs").tabs();
    $("#tabs").tabs('select', selectedTab);
});

The page is now only responsible for rendering the ‘selectedTab’ variable.

<script type="text/javascript">
    var selectedTab = 3;
</script>

I have created a JavaScriptVariable class to assist in rendering the JavaScript variables.   The JavaScript block is rendered to the page using ScriptManager.RegisterStartupScript to ensure the variable are available to scripts.  In addition, the ‘JavaScriptVariables’ member variable and the RenderJavaScriptVaraibles() method could be added to a base Paqe class.  Here is an example using JavaScriptVariable to render the variables for example above.

    IList<JavaScriptVariable> JavaScriptVariables = new List<JavaScriptVariable>();
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        JavaScriptVariables.Add(new JavaScriptVariable("selectedTab", selectedTab.ToString(), "{0}"));
        ScriptManager.RegisterStartupScript(this, typeof(AspNetDiag), "AspNetDiagVars.js", RenderJavaScriptVariables(), true);
    }

    private string RenderJavaScriptVariables()
    {
        StringBuilder js = new StringBuilder();
        foreach (var jsVar in JavaScriptVariables)
        {
            js.AppendFormat("var {0} = {1};", jsVar.Name, jsVar.GetFormatedValue());
        }
        return js.ToString();
    }

Finally the source for JavaScriptVariable.  

class JavaScriptVariable
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }

    public JavaScriptVariable(string name, string value) : this(name, value, "\"{0}\"") { }
    public JavaScriptVariable(string name, string value, string format)
    {
        Name = name;
        Value = value;
        Format = format;
    }

    public string GetFormatedValue()
    {
        return String.Format(Format, Value);
    }
}

Calling a button click from JavaScript in ASP.NET

ASP.NET web forms page have a JavaScript method for handling PostBacks called “__doPostBack”.  This function is used to submit button clicks back to the server.

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

The cool thing is that you can take advantage of the same methods that the framework uses to generate javascript for button clicks.  Use the following in your code file to generate the JavaScript that performs the PostBack. Using this method will ensure that the proper ClientID for the control is used.

protected string GetLoginPostBack()
{
    return Page.ClientScript.GetPostBackEventReference(btnLogin, string.Empty);
}

Then in the ASPX page add a javascript block.

<script language="javascript">
function btnLogin_Click() {
  <%= GetLoginPostBack() %>;
}
</script>

The final javascript will be rendered like this.

<script language="javascript">
function btnLogin_Click() {
  __doPostBack('btnLogin','');
}
</script>

Now you can use “btnLogin_Click()” from your javascript to submit the button click to the server.