Posted on June 2, 2009 17:41 by swilliams

In the project I am currently working on, we are using JavaScript and jQuery in just about everything. One of the frustrations that I have been seeing is that I’ll render a view representing an object, but also want a JSON version of that object to manipulate. I am also quite anal when it comes to keeping my code clean and separating the concerns; I did not want to have JavaScript strewn throughout my HTML or vice versa.

I considered a couple of options. The first just involved making an AJAX call to the server and having it return a JsonResult. This is clean, but I did not want to effectively double my calls to the server.

I also considered extending the MVC framework and writing my own ActionResult class that returned both HTML and JSON. However, that also “felt” wrong; like I was short-circuiting the framework. I would have had to rely on JavaScript on the client side to parse the resulting object and place the HTML, not something I want to be doing with all of my views.

I let it sit on the backburner for a while, and then today came up with a pretty good solution. It’s not ideal, but it works well enough for me. I created a simple HtmlHelper extension that just dumps the JSON out into a variable:

    
using System.Web.Script.Serialization;

    public static class JsonExtensions {
        public static string Json(this HtmlHelper html, string variableName) {
            return Json(html, variableName, html.ViewData.Model);
        }

        public static string Json(this HtmlHelper html, string variableName, object model) {
            TagBuilder tag = new TagBuilder("script");
            tag.Attributes.Add("type", "text/javascript");
            JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
            tag.InnerHtml = "var " + variableName + " = " + jsonSerializer.Serialize(model) + ";";
            return tag.ToString();
        }
    }

You call it from a page like so:

<%= Html.Json("foo") %>
<%= Html.Json("bar", Model.Something) %>

This is not an ideal solution, you are still technically putting JavaScript in the HTML. But, it does not make an extra call to the server, and the markup in the IDE is still very clean.

Another approach I considered was to have an Action that returned a JavaScriptResult that consisted of the same thing. You could then add a script tag like:

<script type="text/javascript" src="/javascript/MyObject/1000">

The catch though is that it would cause more overhead, especially if the app was designed in such a way that the retrievals are expensive (ours is).

I’m still ruminating on that perfect scenario, but for now I’ll be doing it this way.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on May 14, 2009 13:04 by swilliams

Just prior to their 1.0 release, the ASP.NET MVC dev team added a nice feature to prevent CSRF attacks, the AntiForgeryToken. In brief, a CSRF attack is when a 3rd party gets one of your users to accidentally run a malicious script that accesses normally restricted URLs. The AntiForgeryToken pattern allows the web server to reject requests that come from places it was not expecting. More details can be found here. If you are a web developer and aren’t familiar with CSRF attacks, you need to fix that.

Anyways, the AntiForgeryToken bit is all well and good, but what if you are using jQuery (or another library) to handle your AJAX calls? Say you have an Action method like this:

[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult DeleteAccount(int accountId) {
    // delete stuff
}

And you call it via:

$.post('/home/DeleteAccount', { accountId: 1000 }, function() {
    alert('Account Deleted.');
});

Since the POST does not include the AntiForgeryToken, it will fail.

Fortunately, it doesn’t take much brainpower to fix this. All the client side component of AntiForgeryToken does is put the token in a basic hidden field. So, you just need to pull that data out and include it in your AJAX call.

var token = $('input[name=__RequestVerificationToken]').val();

$.post('/home/DeleteAccount', { accountId: 1000, '__RequestVerificationToken': token }, function() {
    alert('Account Deleted.');
});

Do note that if you have multiple forms on the page with multiple AntiForgeryTokens, you will have to specify which one you want in your jQuery selector. Another gotcha is if you are using jQuery’s serializeArray() function, you’ll have to add it a bit differently:

var formData = $('#myForm').serializeArray();
var token = $('input[name=__RequestVerificationToken]').val();
formData.push({ name: '__RequestVerificationToken', value: token });

$.post('/home/DeleteAccount', formData, function() {
    alert('Account Deleted.');
});

Again, if you are making a web site that has any sort of interactivity at all, you need to be aware of these kinds of attacks. The tools to prevent them are readily available for you to use.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on May 11, 2009 21:36 by swilliams

I'm a big fan of the ASP.NET MVC framework. I love the fine grained control it gives you over everything. But what I love most is that you can unleash the fully armed and operational firepower of jQuery.

Recently, I've been working on a site that is using both MVC and jQuery to make AJAX calls. Typically the method being called returned HTML (via a PartialView). But, if an error was thrown, I wanted to return a JSON object encapsulating it.

Unfortunately, jQuery could not decide how to handle a response that could be either HTML, or a JSON object. You can tell jQuery what to expect, or let it try to figure out what the response dataType is. Here's the behavior of my Action method:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult HandleAjax(int id) {
    try {
        var myObj = RetrieveData(id);
        return PartialView("myview", myObj);
    } catch (Exception ex) {
        return Json(new { success = false, message = ex.Message });
    }
}

The problem is that regardless of what gets returned, jQuery only recognizes it as a string, and treats it as HTML.

I did think of one solution, but it used pretty poor design: it attempted to parse the responseText as JSON. If that was successful, it meant the error object was returned. But, if an exception was thrown, it was the HTML. The problem is that it was using error handling mechanisms to capture an expected result. Bad news; I'm not even going to post the code.

Fortunately, someone pointed out that if I set the http status code to 500, jQuery will send the result to the error() callback function, as opposed to success(). Thus, if you added:

this.Response.StatusCode = 500;

In the catch block, you can then use jQuery's error() callback to do exactly as you'd expect:

$.ajax({
    data: { id: 100 },
    dataType: 'html',
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        var errorObj = JSON.parse(XMLHttpRequest.responseText);
        handleError(errorObj);
    },
    success: function(data) {
        $('#resultContainer').html(data);
    },
    url: '/home/HandleAjax'
});

This also makes use of Crockford's JSON library to parse the responseText string to a JSON object.

It is this transparency that makes me sing the praises of the MVC framework. Such a mechanism is certainly possible with classic WebForms, but it is hidden under layers of abstraction, and likely would have required mixing of markup, script, and server side code.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 5, 2008 05:57 by mcollins

While I am a fan of using Microsoft's AJAX framework in my ASP.NET applications, I am realistic and admit that it does some things well, but for other things, sometimes there's a better way.  Take the following web page for example:

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <div id="faq">
  14:         <h2><a href="#">Question 1</a></h2>
  15:         <div>
  16:             <p>Answer 1</p>
  17:         </div>
  18:         <h2><a href="#">Question 2</a></h2>
  19:         <div>
  20:             <p>Answer 2</p>
  21:         </div>
  22:     </div>
  23:     <asp:Panel ID="DebugPanel" runat="server" Visible="false">
  24:         <textarea id="TraceConsole" rows="30" cols="60"></textarea>
  25:     </asp:Panel>
  26:     </form>
  27:  
  28:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         Sys.Application.add_init(function() {
   4:             Sys.Debug.trace('Initializing page.');
   5:  
   6:             // Create client components. Initialize the page.
   7:             
   8:             Sys.Debug.trace('Page initialized.');
   9:         });
  10:         
  11:         function pageLoad() {
  12:             Sys.Debug.trace('pageLoad called.');
  13:             
  14:             // Begin executing the business logic for the page. Attach
  15:             // event handlers to elements, etc.
  16:             
  17:             Sys.Debug.trace('pageLoad completed.');
  18:         }
  19:         
  20:         function pageUnload() {
  21:             Sys.Debug.trace('pageUnload called.');
  22:             
  23:             // The page is being unloaded. If you attached event
  24:             // handlers in pageLoad, detach them here to prevent
  25:             // memory leaks.
  26:             
  27:             Sys.Debug.trace('pageUnload completed.');
  28:         }
  29:     //-->
  30:     
</script>
  29:  
  30: </body>
  31: </html>

This code template is a standard FAQ that has two questions and two answers.  Typically, when you see a page like this in a browser, you may come across the FAQ hiding the answers and showing you a list of the questions.  When you click on a question, then the answer will display itself.  To accomplish this feat, we'll use a little JavaScript, DOM, and CSS manipulation to show and hide the answers.  Here's the code with JavaScript using the Microsoft AJAX framework:

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <div id="faq">
  14:         <h2><a href="#">Question 1</a></h2>
  15:         <div>
  16:             <p>Answer 1</p>
  17:         </div>
  18:         <h2><a href="#">Question 2</a></h2>
  19:         <div>
  20:             <p>Answer 2</p>
  21:         </div>
  22:     </div>
  23:     <asp:Panel ID="DebugPanel" runat="server" Visible="false">
  24:         <textarea id="TraceConsole" rows="30" cols="60"></textarea>
  25:     </asp:Panel>
  26:     </form>
  27:  
  28:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         Sys.Application.add_init(function() {
   4:             Sys.Debug.trace('Initializing page.');
   5:  
   6:             // Create client components. Initialize the page.
   7:             
   8:             Sys.Debug.trace('Page initialized.');
   9:         });
  10:         
  11:         function pageLoad() {
  12:             Sys.Debug.trace('pageLoad called.');
  13:             
  14:             var faq = $get('faq');
  15:             var questions = faq.getElementsByTagName('H2');
  16:             for (var i = 0; i < questions.length; i++) {
  17:                 questions[i].nextSibling.style.display = 'none';
  18:                 $addHandler(questions[i].firstChild, 'click',
  19:                     toggleAnswer);
  20:             }
  21:             
  22:             Sys.Debug.trace('pageLoad completed.');
  23:         }
  24:         
  25:         function pageUnload() {
  26:             Sys.Debug.trace('pageUnload called.');
  27:             
  28:             var faq = $get('faq');
  29:             var questions = faq.getElementsByTagName('H2');
  30:             for (var i = 0; i < questions.length; i++) {
  31:                 $removeHandler(questions[i].firstChild, 'click',
  32:                     toggleAnswer);
  33:             }
  34:             
  35:             Sys.Debug.trace('pageUnload completed.');
  36:         }
  37:         
  38:         function toggleAnswer() {
  39:             Sys.Debug.trace('toggleAnswer called.');
  40:             
  41:             var answer = this.parentNode.nextSibling;
  42:             if (answer.style.display == 'none') {
  43:                 answer.style.display = 'block';
  44:             } else {
  45:                 answer.style.display = 'none';
  46:             }
  47:             
  48:             Sys.Debug.trace('toggleAnswer completed.');
  49:             return false;
  50:         }
  51:     //-->
  52:     
</script>
  29:  
  30: </body>
  31: </html>

In the pageLoad function, I begin by using the Microsoft AJAX framework's $get function to get the element with an id of faq.  From there, I get all of the child H2 elements of the FAQ.  Next, I do two things.  First, I hide the block containing the answer to the question.  Second, I attach an event handler to the click event of the A element inside of the H2 element.

Inside of the toggleAnswer function, I look at the current display state of the block containing the answer.  If the block is visible, I hide the block.  If the block is visible, I show the block.

Overall, this code works, but it seems like a lot of code.  Is there an easier way to build this page?

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:         <Scripts>
  13:             <asp:ScriptReference Path="~/jquery-1.2.3.min.js" />
  14:         </Scripts>
  15:     </asp:ScriptManager>
  16:     <div id="faq">
  17:         <h2><a href="#">Question 1</a></h2>
  18:         <div>
  19:             <p>Answer 1</p>
  20:         </div>
  21:         <h2><a href="#">Question 2</a></h2>
  22:         <div>
  23:             <p>Answer 2</p>
  24:         </div>
  25:     </div>
  26:     <asp:Panel ID="DebugPanel" runat="server" Visible="false">
  27:         <textarea id="TraceConsole" rows="30" cols="60"></textarea>
  28:     </asp:Panel>
  29:     </form>
  30:  
  31:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         var $j = jQuery.noConflict();
   4:         
   5:         Sys.Application.add_init(function() {
   6:             Sys.Debug.trace('Initializing page.');
   7:  
   8:             // Create client components. Initialize the page.
   9:             
  10:             Sys.Debug.trace('Page initialized.');
  11:         });
  12:         
  13:         function pageLoad() {
  14:             Sys.Debug.trace('pageLoad called.');
  15:             
  16:             $j('#faq > div').hide();
  17:             $j('#faq > h2 a').click(function() {
  18:                 Sys.Debug.trace('click handler called.');
  19:                 
  20:                 $j(this).parent().next().toggle();
  21:                 
  22:                 Sys.Debug.trace('click handler completed.');
  23:                 return false;
  24:             });
  25:             
  26:             Sys.Debug.trace('pageLoad completed.');
  27:         }
  28:         
  29:         function pageUnload() {
  30:             Sys.Debug.trace('pageUnload called.');
  31:             
  32:             Sys.Debug.trace('pageUnload completed.');
  33:         }
  34:     //-->
  35:     
</script>
  32:  
  33: </body>
  34: </html>

In this new code sample, notice on line #13 in the HTML markup that we're now including a reference to the jQuery library.  jQuery is another JavaScript framework that makes DOM and CSS manipulation significantly easier.  Using jQuery, we've been able to significantly reduce the amount of JavaScript code that we needed to really only about four lines of code if you remove the debugging statements.

The moral of this story is don't limit yourself only to using the Microsoft AJAX library to implement your JavaScript and AJAX layer in your web pages.  The Microsoft AJAX library gives you a lot of tools on both the client and server for implementing AJAX-type logic, but it's not the only player out there and can play just as well with other frameworks such as jQuery. 

If you read up on jQuery, you'll see that jQuery offers page-level events similar to Microsoft AJAX's init event and the pageLoad and pageUnload methods.  So the other question is which framework you should use as your primary.  I typically choose to use Microsoft's AJAX library as my primary and just use the other frameworks as necessary.  I do this because the Microsoft AJAX ScriptManager control is a primary component of my page and I use that as my base library and just add other functionality to it.  There's no right or wrong answer to this one, and everyone will have to make their own decisions.  That's just the way that I do things.

Technorati tags: , , ,


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 4, 2008 20:25 by mcollins

(I reposted this because it accidentally got deleted.)

Building a web application is not so much different than writing a normal desktop application when you consider it from the perspective of the server side.  The main difference is that your web application can be accessed by many users concurrently, while your desktop application is only accessed by a single user.  But in both cases, the applications start up, initialize themselves, and then wait and respond to user inputs to perform business logic.

When considering the client side of things in a web application, it becomes a little different.  A typical web application is made up of many web pages that are served to the user.  The user will typically navigate between the web pages by clicking hyperlinks or by pressing buttons that cause the server to redirect them to a different web page.  However, from the browser's perspective, each web page is a new application.  As such, a web page must also go through the initialization and wait for stimulus process that a typical application will go through.

The ASP.NET AJAX framework has support for building web pages and alerting them when they need to initialize.  The ASP.NET AJAX framework implements a global page manager object named Sys.Application that is created when the page is being loaded and manages alerting the page's JavaScript code when the page should be initialized, when the page has been loaded and should start running its business logic, and when the page is being unloaded and should clean up after itself.  The first event, initializing the page, is handled by the Sys.Application object calling an event handler for the init event.  The second event, telling the page to start running, is implemented by the Sys.Application object calling a special page-scoped function named pageLoad.  And the third event, telling the page to clean up and unload itself, is implemented by the Sys.Application object calling another special page-scoped function named pageUnload.  Your typical ASP.NET AJAX page template would look like this:

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <div>
  14:     </div>
  15:     </form>
  16:  
  17:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         Sys.Application.add_init(function() {
   4:             // Create client components. Initialize the page.
   5:         });
   6:         
   7:         function pageLoad() {
   8:             // Begin executing the business logic for the page. Attach
   9:             // event handlers to elements, etc.
  10:         }
  11:         
  12:         function pageUnload() {
  13:             // The page is being unloaded. If you attached event
  14:             // handlers in pageLoad, detach them here to prevent
  15:             // memory leaks.
  16:         }
  17:     //-->
  18:     
</script>
  18:  
  19: </body>
  20: </html>

The difference to remember between the init event handler and the pageLoad function is that the init event is raised while the page is loading, but before the page is ready.  When the init event is raised, the page has been loaded and the initial DOM tree is accessible, but some things such as images, applets, and other embedded objects most likely haven't been loaded and are not accessible.  You can use the init event to inject elements into the DOM tree or create other client components, but you shouldn't start executing your page's business logic during this event.  When the pageLoad function is called, the page and all of its media elements have been loaded and are rendered, so it's safe to do things such as activate controls, set timers, or begin animations.

Technorati tags: , ,


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 4, 2008 07:13 by mcollins

Let's face it, one of the problems that has always plagued client-side development in the browser is that JavaScript can be a pain to debug.  As a developer, you have no knowledge if the browser is actually executing your code or what is happening when a page loads.  You refresh the page in the browser, wait, and see if your latest changes worked.  If not, you then have to mentally figure out what happened inside your script without really having any tools to see inside.  Sure, Microsoft makes a script debugger for IE, and sometimes script debugging does work inside of Visual Studio, but I've found a lot of times where the scripts won't load in the debugger or breakpoints that I set inside of Visual Studio aren't tripped.  When that doesn't work, I've typically had to fall back to putting alerts into my code and going through many popup message boxes to tell me what's going on.

Fortunately, ASP.NET AJAX has support to make debugging easier through the Sys.Debug JavaScript object.  The Sys.Debug object provides a trace method for outputting simple messages to a trace console and a traceDump method for outputting object contents to the trace console.  So what is the trace console?  If your browser has a JavaScript console then your messages will go there.  Internet Explorer may have one, but I've never found it.  So the other approach is to make your own inside of your web page, which turns out to be quite easy to do.  You simply create a TEXTAREA element inside of your web page and set its ID attribute to the value TraceConsole.  The Sys.Debug object will automatically find it and append your trace output to that element.

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <div>
  14:     </div>
  15:     <textarea id="TraceConsole" rows="30" cols="60"></textarea>
  16:     </form>
  17:  
  18:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         Sys.Application.add_init(function() {
   4:             Sys.Debug.trace('Initializing page.');
   5:             
   6:             // Create client components. Initialize the page.
   7:             
   8:             Sys.Debug.trace('Page initialized.');
   9:         });
  10:         
  11:         function pageLoad() {
  12:             Sys.Debug.trace('pageLoad called.');
  13:             
  14:             // Begin executing the business logic for the page. Attach
  15:             // event handlers to elements, etc.
  16:             
  17:             Sys.Debug.trace('pageLoad completed.');
  18:         }
  19:         
  20:         function pageUnload() {
  21:             Sys.Debug.trace('pageUnload called.');
  22:             
  23:             // The page is being unloaded. If you attached event
  24:             // handlers in pageLoad, detach them here to prevent
  25:             // memory leaks.
  26:             
  27:             Sys.Debug.trace('pageUnload completed.');
  28:         }
  29:     //-->
  30:     
</script>
  19:  
  20: </body>
  21: </html>

Here's a screen shot of the trace output in the page:

image

Of course, what happens if you don't want this console to show up on pages in the production environment.  You can wrap the trace console element inside of a Panel control, and then choose to show or hide the panel depending on whether the page is in debug mode or not.

   1: <%@ Page Language="C#" AutoEventWireup="true" ... %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   4:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <div>
  14:     </div>
  15:     <asp:Panel ID="DebugPanel" runat="server" Visible="false">
  16:         <textarea id="TraceConsole" rows="30" cols="60"></textarea>
  17:     </asp:Panel>
  18:     </form>
  19:  
  20:     <script type="text/javascript">
   1:  
   2:     <!--
   3:         Sys.Application.add_init(function() {
   4:             Sys.Debug.trace('Initializing page.');
   5:             
   6:             // Create client components. Initialize the page.
   7:             
   8:             Sys.Debug.trace('Page initialized.');
   9:         });
  10:         
  11:         function pageLoad() {
  12:             Sys.Debug.trace('pageLoad called.');
  13:             
  14:             // Begin executing the business logic for the page. Attach
  15:             // event handlers to elements, etc.
  16:             
  17:             Sys.Debug.trace('pageLoad completed.');
  18:         }
  19:         
  20:         function pageUnload() {
  21:             Sys.Debug.trace('pageUnload called.');
  22:             
  23:             // The page is being unloaded. If you attached event
  24:             // handlers in pageLoad, detach them here to prevent
  25:             // memory leaks.
  26:             
  27:             Sys.Debug.trace('pageUnload completed.');
  28:         }
  29:     //-->
  30:     
</script>
  21:  
  22: </body>
  23: </html>

You can see here on line 15 that I wrapped the TEXTAREA element with an ASP.NET Panel control named DebugPanel.  Initially the panel's Visible property is set to false, meaning that the Panel control and it's contents won't be rendered by the page when the page is requested.  In the code-beside file for the page, I handle displaying the Panel control when the Page.Load event is raised:

   1: public partial class _Default : System.Web.UI.Page {
   2:     protected void Page_Load(object sender, EventArgs e) {
   3:         ShowDebugConsole();
   4:     }
   5:  
   6:     [Conditional("DEBUG")]
   7:     private void ShowDebugConsole() {
   8:         DebugPanel.Visible = true;
   9:     }
  10: }

In the code-beside file for the page, by Page_Load handler is being called when the page is being requested by a user.  Inside of the event handler, it's invoking the ShowDebugConsole method.  The ShowDebugConsole method is simply setting the value of the Visible property on the DebugPanel control to true to indicate that the debugging console should be rendered in the page's output.  The real magic here is in the use of the Conditional attribute on the ShowDebugConsole method.  When the page is being compiled in debug mode, then the C# compiler will define the DEBUG symbol.  When the DEBUG symbol is defined, the compiler will compile the code inside of the ShowDebugConsole method, and thus the debugging console will be displayed in the rendered HTML and on the browser.  When the page is being compiled in release mode, the DEBUG symbol is not defined and the code inside of the ShowDebugConsole method is not compiled.  The ShowDebugConsole method will still be included in the generated IL code, but the method will be empty and will simply return to the caller.

The next part of the magic is how do you tell an ASP.NET application that it's running in debug mode versus release mode.  There are two ways of doing this.  If you're using an ASP.NET Web Application project for your web application, or if you are using a Web Deployment Project to compile and package your web application, then the build mode is determined by the compiler at build time.  For example, this is handled from the toolbar in Visual Studio by choosing between a debug build or a release build.  The other ASP.NET mode for web applications is to deploy the .aspx files side-by-side with the .cs files and ASP.NET will compile pages as they are requested.  In this case, you need some other way to tell ASP.NET to compile the pages in debug or release mode.  It turns out that this can be done using the web.config file:

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <system.web>
   4:         <compilation debug="true">
   5:             <assemblies>
   6:                 ...
   7:             </assemblies>
   8:         </compilation>

Above is a fragment of my web.config file.  Line 4 is the line that we need to focus on.  Notice that the debug attribute on the compilation element is set to true.  When this value is set, then the runtime ASP.NET compiler will build the pages in debug mode and will define the DEBUG symbol for the C# compiler.  Setting the value of the debug attribute to false will turn off debug mode for the web application.  You can therefore control whether the debugging console appears on your pages using the web.config file.

In summary, the Sys.Debug object provides a lot of advantages to JavaScript debugging at runtime over using the JavaScript alert function.  First, you don't need to deal with those annoying message boxes and removing them after you've fixed your bug.  Second, by using a little .NET and ASP.NET creativity, you can add debugging support to your pages that you can easily disable in the production environment by modifying your web.config file and not your source code.  The end result is that you have a page that is easier to debug and easier to maintain in the long run.

Technorati tags: , , ,


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 3, 2008 21:53 by mcollins

When I hear people talk about AJAX, I often hear about the removal of page refreshes or the ability to asynchronously call web services on the server from the browser.  I see many developers around me using the AJAX Control Toolkit and calling that AJAX because of the watermark control or other controls, but I think that most developers miss the mark on the prime feature of AJAX: JavaScript.  Or at least, in my opinion, it's JavaScript.

I tried JavaScript a long time ago when it first came out.  I honestly did.  And I passed on it because it really didn't do what I wanted it to, or maybe I understood how to use it.  And it was a different time when each browser did things their own way.  To some extent, each browser still does things their own way, but at least they're getting closer.  But I bought the books about JavaScript programming, I read them, I tried the techniques, and I got too tired of dealing with browser differences and the fact that it was far easier to debug server-side code than client-side JavaScript code.

Flash forward a few years into the modern age of web development where Web 2.0 has made developing web applications cool again.  My interest in JavaScript was first aroused once again with two books that I found.  The first book, DOM Scripting: Web Design and JavaScript and the Document Object Model by Jeremy Keith and published by friends of ED, reintroduced me to JavaScript and helped me see what could be accomplished with JavaScript in the modern generation of browsers.  The next book, AdvancED DOM Scripting: Dynamic Web Design Techniques by Jeffrey Sambells and Aaron Gustafson and also published by friends of ED helped me to really understand the object-oriented nature of JavaScript, how to build JavaScript libraries, and how to find and take advantage of third-party JavaScript libraries such as Prototype, Script.aculo.us, and jQuery.

JavaScript, in its current incarnation, is a powerful and capable language and stands on its own when compared to the current masters of the programming landscape: C# and Java.  It is just as object-oriented as both languages, and in some ways a lot more flexible.  Most importantly, JavaScript is the language, unlike C# and Java, that is going to lead the Web 2.0 generation.  Kind of ironic for a language that was dismissed not so long ago as something that nuisances were made of.

If you set no other goals for yourself for 2008, make 2008 the year that you sit down and return to JavaScript.  It's a tool that needs to be in your toolbox, and when everyone else in the room is talking AJAX, you'll be the one actually doing it.  AJAX is more than XML and UpdatePanels.  It's all about JavaScript and the browser that is being controlled by your JavaScript.

Amazon.com: DOM Scripting

ISBN: 1590595335
ISBN-13: 9781590595336

Amazon.com: AdvancED DOM Scripting

ISBN: 1590598563
ISBN-13: 9781590598566

Technorati tags: ,


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 2, 2008 08:19 by mcollins

ASP.NET AJAX in Action by Alessandro Gallo, David Barkol, and Rama Krishna Vavilala, is one of the best books that I've seen covering AJAX from the Microsoft perspective.  Their book is wonderful at giving the reader the exact details that they need to know about how to take advantage of Microsoft's AJAX technologies on both the client and the server, as well as getting the client and the server to work together.

When you think of Microsoft AJAX, most developers would probably think first of the UpdatePanel control in ASP.NET.  Using UpdatePanel is easy.  The developer drops it onto a page, adds one or more ASP.NET server controls as content for the UpdatePanel, and instantaneously those nasty page refreshes go away.

What most developers, in my opinion, are not thinking about when they hear the term Microsoft AJAX is the rich client-side library written in JavaScript that allows developers to do so much more on the client side.  The authors recognize this problem and spend significant time explaining the richness of the JavaScript environment before introducing the concept of the UpdatePanel control.  The end result of this book is that the developer has started to master the client-side development aspects of developing with JavaScript and calling web services on the server by the time the developer starts looking into the server-side aspects of AJAX.

Special attention in the second half of the book is placed on the component and control model of the Microsoft AJAX library.  Developers will learn how to create new non-visual JavaScript components, behavior extenders in JavaScript, and new JavaScript-based HTML controls.  Once the client-side aspects of these components and controls have been covered, the authors then explain and demonstrate how to wrap your new JavaScript components in ASP.NET server controls to enable the drag-and-drop designer experience.

This book is easy to read.  I found very few errors in it (none that I can actually recall).  Overall, this book really helped me to better understand and advance my use of Microsoft's AJAX technologies and pushed me into spending a lot more time learning how to develop in JavaScript on the browser, something which I admittedly was not very good at.  I definitely recommend buying this book the next time that you're at Borders.

Amazon.com: ASP.NET AJAX in Action

ISBN: 1933988142
ISBN-13: 9781933988146

Technorati tags: , , , ,


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on March 2, 2008 08:07 by mcollins

Try the AJAX Loading GIF Generator at Web Script Lab.

Technorati tags:


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5