Webservices Posts

  • Per Lundberg (gravatar)

    In this posting, I’ll give an introduction to how you can use the new features provided by ASP.NET AJAX to call methods in web services from your own JavaScript code with very little fuss. (Well, at least that’s the idea…)

    First, I want to take some steps backward and describe the history, the steps that led to the advent of ASP.NET AJAX. JavaScript has historically been a client-only language, providing some client-side events that can be used to e.g. perform certain events every time the user hovers the mouse over a certain part of the web page, or every time an HTML <button> is clicked. All of this is taking place on the client computer only, in the web browser. There is no interaction between the JavaScript code and the server providing the web page on which the JavaScript code is hosted.

    As the web applications started to be more and more advanced, the need for more interaction arose. The gap between the client and the server needed to be eradicated, somehow. The solution - or bridge, if you like - is named XMLHttpRequest. This is the very foundation that all of AJAX (including ASP.NET AJAX) relies upon.

    XMLHttpRequest is a mechanism through which a web browser (Firefox, Internet Explorer, Safari, etc.) can make a request to the server without refreshing the whole page. The request is made by client-side script, in other words, JavaScript (as much as we love it or hate it…). The initial implementation of the XMLHttpRequest was made by Microsoft as a wrapper on top of the MSXML, using ActiveX (so it was not a “pure” JavaScript functionality at that time; rather JScript). Later on, other browser vendors followed along, modeling their implementation after the Microsoft one, and eventually the XMLHttpRequest was standardized by the W3C. [1]

    So, what good does this XMLHttpRequest API do? Well, as previously mentioned, it enables client-side code (JavaScript) running in the web browser to make server-side requests for certain information, without the need for a full page reload. This makes all forms of interesting interactive web sites (or rather, web applications is a more descriptive term) possible. For example, you could have a page fetch live news from a newsfeed server, and display it on a web server, without the need for any refreshing of the page. You could have a form where the user enters a monetary value and chooses the source/target currencies, and presses a “Convert” button. The value is then converted between the given currencies, with no need for any 1990’s-style page refreshing. :-)

    In the Microsoft ASP.NET world, ASP.NET AJAX was introduced between the release of ASP.NET 3.0 and 3.5 (a pre-release named Atlas was available slightly earlier). ASP.NET 3.5 (Visual Studio 2008) has ASP.NET AJAX support out-of-the-box.

    (In the ASP.NET AJAX nomenclature, Microsoft talks about this “avoiding full page refresh” thing as partial page updates. I’ll use this phrase for the rest of this article.)

    ASP.NET AJAX can be used in two modes: “ASP.NET mode” and “JavaScript mode”. In ASP.NET mode, what you do is basically more or less embed the controls that you want to use partial-page updates for in an <asp:UpdatePanel/> control. That way, ASP.NET AJAX will “seamlessly” handle the page updates, and tunnel them through the AJAX (XMLHttpRequest) pipe. Very convenient and easy to use for the developer, but not always optimal from a performance and technical point of view. I did a simple test when writing this blog article. The source code to my test page looks like this:

    <%@ Page Language="C#" AutoEventWireup="true" %>
    
    <script type="text/C#" runat="server">
    
        protected void Button_Click(object sender, EventArgs e)
        {
            Label.Text = "Moo!";
        }
        
    </script>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <asp:ScriptManager EnablePartialRendering="true" runat="server" />
        <asp:UpdatePanel ID="UpdatePanel" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button" runat="server"
                            Text="Click Me!"
                            OnClick="Button_Click" />
                <asp:Label ID="Label" runat="server" />
            </ContentTemplate>
        </asp:UpdatePanel>
        </form>
    </body>
    </html>

    In other words, quite a simple page. The idea is that you click a button, and the button makes the text for a certain control be changed to “Moo!”. Since this is embedded in an UpdatePanel, this is supposed to take place using partial-page rendering techniques. The page looks like this when rendered:

     "Click Me" web page

    Now, let’s inspect what it looks like in Fiddler when the “Click Me!” button is clicked. This is what we get:

    Fiddler output of the UpdatePanel request

    The amount of overhead is immense; not speaking byte-wise, but percentage-wise. What we wanted to do is to fetch the “Moo!” text and place it in a control. This is a four byte string (if we’re talking ASCII and not UCS-2…) + maybe a trailing CR+LF or something like that. Let’s be nice and say that 10 bytes for this update would be reasonable.

    Instead, we got 571 characters being sent over the wire. That’s an incredible 5700% of the “reasonable size” being used for the request!

    Now, in reality, this is much less of a problem than I’m making it appear to be… Computers are fast nowadays, and broadband connections are common. Still, that old 640 KiB geek in me screams when I see something like this… :-) And of course, in this example, it might not be a problem, but who’re saying it wouldn’t be in a more complicated use case? What if you have more controls on the page, more viewstate to persist (which could be disabled altogether, btw.) and so forth? This can actually turn out to be a performance killer.

    The reason for this extraneous information being transferred is this: The UpdatePanel control is built in a generic way. If you look closely at my screenshot (click on it to see the full picture), you see that what is transferred is the full HTML for the content of the UpdatePanel control. This makes it simple to implement (in the UpdatePanel control itself), and also has some other advantages, but is sometimes very much less than optimal, and can also make the page give a more sluggish feeling than necessary.

    In our specific example, what we could have done instead is to just get the updated Text field and set the innerHTML property of the Label to this value. This should provide a much more optimized experience. :-) By using the client-side ASP.NET AJAX functionality, this is actually quite simple! I’ll go ahead and add a webservice to my web project, called “LabelWebService.asmx”. The .asmx file is left unmodified, and the code-behind file is modified to look like this:

    using System.Web.Script.Services;
    using System.Web.Services;
    
    namespace eCraft.AjaxWithUpdatePanel
    {
        /// <summary>
        /// Simple webservice for fetching the text for a label on a web page.
        /// </summary>
        [WebService(Namespace = "http://labs.ecraft.com/Samples/CallingWebServicesFromJavascript/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [ScriptService]
        public class LabelWebService : WebService
        {
            [WebMethod]
            public string GetText()
            {
                return "Moo!";
            }
        }
    }

    In other words, a very simple proof-of-concept web service that just returns a dummy value. Note the special attribute ScriptService on this class (from the System.Web.Script.Services namespace). What this attribute does is enable JavaScript proxy generation for your web service, enabling the service to be called from JavaScript embedded in an ASP.NET page. We might go through how this works behind the scenes some other time; for now, just accept the fact that it somehow magically creates a JavaScript wrapper class that lets you call your web service from JavaScript.

    So, let’s skip the talk and go straight on to the code, shall we? This is the modified test page, now with some embedded code for calling the web service through JavaScript:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="eCraft.AjaxWithUpdatePanel.Default" %>
    
    <script type="text/javascript">
           
        function Button_Click()
        {
            var ws = new eCraft.AjaxWithUpdatePanel.LabelWebService;
            ws.GetText(GetText_Succeeded);        
        }
    
        function GetText_Succeeded(result)
        {
            var label = $get('<%= Label.ClientID %>');
            label.innerHTML = result;
        }
        
    </script>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
    </head>
    <body>
        <form id="form2" runat="server">
        <asp:ScriptManager ID="ScriptManager1"
            EnablePartialRendering="true" runat="server">
        <Services>
            <asp:ServiceReference Path="~/LabelWebService.asmx" />
        </Services>
        </asp:ScriptManager>
            
        <asp:Button ID="Button" runat="server" Text="Click Me!"
            OnClientClick="Button_Click(); return false;" />
        <asp:Label ID="Label" runat="server" />
        </form>
    </body>
    </html>

    As you see, the page has been slightly changed from before. Maybe one of the most important changes that has taken place is that we skipped the <asp:UpdatePanel/> control altogether, but kept the <asp:ScriptManager/> one. We also added an <asp:ServiceReference/> control. This is what makes the page aware of the web service that we are about to call, and it helps the JavaScript intellisense to recognize the proxy class representing our web service.

    We have also introduced two new JavaScript functions: Button_Click() and GetText_Succeeded(). The <asp:Button/> control have also been modified to perform an OnClientClick rather than an OnClick event. (The “return false” part is important, since we would otherwise get a full page postback – that’s the default behavior of the <input type=”button”> element, which is what the Button control gets rendered as.)

    In the Button_Click() function, we create an instance of our web service wrapper class. The cool thing about this is that if you remove the code inside that function, and start typing “var ws = new e“, you should get something like this:

    Calling web services from JavaScript - intellisense screenshot

    The eCraft.AjaxWithUpdatePanel.LabelWebService class is apparently known to Visual Studio, helping us a lot. You can now use code-completion to write the full class name, just like you could for C# code. This is a good enhancement that Microsoft has done to the JavaScript language, making it more convenient to work with (even though I’m really looking forward to a possible successor to the JavaScript language altogether… The language is too “weak” and dynamic in my taste.)

    If you look at my Button_Click code again, something noteworthy is that the web service call is done slightly different than it would be done in C#. Instead of just calling the web service and getting back the result as a return value from the method, we are setting up a callback that will get called once the web service method is finished. This is a clear difference from traditional web service client code. This shows the asynchronous nature of the AJAX technology (after all, that’s what the A in AJAX stands for…). All web service calls are asynchronous when being used from JavaScript like this, and asynchronous service calls usually use callbacks to call a user-supplied method/function when the call has finished.

    The disadvantage of this is that your code can become harder to read; it is less obvious what the flow looks like. The advantage is that you can make multiple server requests at once, and in a load-balancing scenario, there could even be multiple physical servers to serve your different requests, increasing performance. It is also a good preparation for starting to work with service calls in Silverlight, which always uses asynchronous calls (at least when calling WCF services, but I guess the same goes for traditional web services as well).

    Finally, let’s look at the Fiddler output for my modified version of the program. You’ll be amazed (we hope :-). This is what it looks like:

    Fiddler output of the JavaScript web service request

    Whoha! What’s that? It clearly looks very different to before, and also extremely optimized.

    The reason why the content here looks very differently is that we’re now making a web service call rather than getting HTML data for updating the UpdatePanel. But also, it doesn’t look like the SOAP stuff that you could expect to get back from a normal web service call. This is because it uses the JSON format for serializing the data. JSON is a highly optimized format for serializing data over e.g. HTTP connections, and it is the default when using the ScriptService attribute like we’re doing here. (It usually works well, but it might not be suitable for all web service calls, perhaps especially if the data you are returning is of XML format. If necessary, you can always change to “raw XML”  as the response format. See this external blog posting for more details on that.)

    Regarding the performance, we can see that the 571 bytes from the UpdatePanel sample has now shrank to a whopping 12 bytes. Quite an improvement (97,9% actually…). With the risk of being repetitive; in this case, it might not have mattered that much, but you should be able to clearly see the potential that this method has over standard <asp:UpdatePanel/> usage. The performance is simply outstanding. The cost you have to take is that you have to write client code to update the contents of the HTML controls. Sometimes, this can be a bit of work, but it can be simplified a bit. (instead of e.g. creating an HTML table with rows and cells, you could create it from beforehand and just use style=”display: none” to hide the cells. This makes it easy to un-hide them through JavaScript; hopefully simpler or better than inserting a bunch of new nodes in the DOM tree…)

    Alright, time to close up this blog posting. In this posting, we have gone through the basics behind how AJAX works. We have also done some field testing of ASP.NET AJAX performance, first using UpdatePanel and later on using direct web service calls from JavaScript. We saw the clear performance advantage with JavaScript calling a web service vis-a-vis using the UpdatePanel, but can also understand that the UpdatePanel is often a better (or at least “simpler to implement”) choice, especially if you have a lot of code and controls in the existing implementation that you simply want to AJAXify. The UpdatePanel also makes the code slightly simpler to read and understand, since it “looks” more like traditional ASP.NET code (but this might actually be a disadvantage, since it works differently under the hood – abstraction can be good, but it can also fool you at times).

    Anyway, we now know the alternatives, so we can wisely consider them both in real-world scenarios, and use whichever one is more suitable in each specific case. Remember that system architecture is no “one size fits all” business.

    See you in my future posts; until then, take care.

  • Per&#32;Lundberg (gravatar)

    As mentioned in a previous posting, Fiddler can be a great tool when debugging HTTP-based communication, particularly for webservices, WCF and similar (but really, any kind of HTTP traffic can be debugged with the tool). There is just one slight problem with it: by default, it is not usable for debugging localhost-based servers. In other words: if your server URL looks something like http://localhost:12345/MyService.asmx, you will not be able to debug it with Fiddler. That is, unless you apply “The Dot Trick”, which will be described in this blog posting.

    First, let’s discuss the apparent problem and its cause, then we’ll move on to how we can workaround this. Let’s create a scenario: You are having problems with a web request in an application; the web request causes an exception for some reason. More specifically, the request is from a web application (ASP.NET .aspx file) to a web service (.asmx file). Also, you cannot/don’t want to debug this using Visual Studio’s built-in debugger, for one reason or another. This is the error message you’re getting, as presented on the ASP.NET web page:

    An ASP.NET page with an error message

    Now, let’s start Fiddler. This is the output we get:

    Fiddler startup screen

    Switch back to IE, and press F5 to refresh the page (and hopefully reproduce the problem). After doing this, the error appears again in the web page, but… if you now look in the Fiddler window, it looks exactly the same as before you hit F5. How could this be, what on earth is happening?!?

    The answer is this, taken from the Fiddler web page: “Internet Explorer and the .NET Framework are hardcoded not to send requests for Localhost through any proxies, and as a proxy, Fiddler will not receive such traffic” [1] This makes sense if you think about it: a proxy running somewhere in your local network can not fetch data from your local machine, when accessing a localhost-based URL. It could do a best-effort and try to rewrite the url to http://yourmachine:12345 (where yourmachine is the name of your machine), using the IP address provided in the proxy request, but… there’s no guarantee that http://yourmachine:12345 would be the same as your local http://localhost:12345 URL. In fact, when using the Visual Studio built-in web server (a.k.a. Cassini), this would not work at all: Cassini is designed to only listen on localhost traffic!

    Therefore, it is understandable that someone at Microsoft at some point took the decision that WinINET and/or IE/Microsoft.NET  should disregard proxy configurations for localhost-based URL:s.

    So, having stated what the problem is and some theory behind it, let’s move on to the whole point of this blog posting: There is a nifty little workaround to this problem, making it possible to debug traffic to localhost in Fiddler! But only if you have a way to modify the URL, so in some cases it would still be hard/impossible to use this. In our specific use case (an ASP.NET page calling a webservice) though, we can benefit greatly from knowing this. The workaround is what we can call “the Dot Trick”.

    What you simply do is this: change the URL from something like http://localhost:12345/MyService.asmx to be http://localhost.:12345/MyService.asmx. Did you notice the dot? Right after the “localhost” and before the colon a dot (period character) has been inserted. This is what the browser window with the ASP.NET page looks like now (very similar to before, only difference being that the dot has been inserted in the URL):

    The ASP.NET browser window again, with URL modified

    But now look at our Fiddler buddy! This is what the Fiddler window contains:

    The Fiddler output, now including the localhost traffic

    Much better, isn’t it? We can now investigate “the red line” and possibly see what was causing this problem. However, that is out of the scope for this blog posting. :-)

    Alright, that’s it for this time. In this blog posting, we’ve learned one of the caveats of Windows HTTP traffic, and how to work around it. I hope the information was useful to some of you; it has sure helped me.

    PS: Rumor has it that “the dot trick” sometimes doesn’t work, e.g. with Windows 7. In that case, you can try http://ipv4.fiddler:12345/MyService.asmx instead. This will be intercepted by Fiddler and converted to localhost:12345, intercepting the traffic as needed.

  • Per&#32;Lundberg (gravatar)

    As many of you know, a debugger is an invaluable tool for a software developer. A good debugger really helps when tracking down some problem with the software you (or someone else) has written.

    On the other hand, when you don’t have the ability to single-step the code through a debugger, or when you get poor, non-descriptive error messages, it can really be a nuisance. In this blog posting, I will go through the second of these cases (i.e. non-descriptive error messages).

    When working with WCF services, the error messages can sometimes be really unintelligible. Or rather: they don’t tell you very much about the problem. This is the error message I got today when using a WCF service from within a Silverlight 3 application:

    Visual Studio exception crossed managed-native boundary

    Allright. Let’s peek into the View Detail box, shall we? This is what it looked like, after expanding some InnerExceptions:

    image

    The stack trace looked like this:

    {System.Net.WebException: The remote server returned an error: NotFound.
       at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
       at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
       at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)}

    Not very descriptive, huh? So, maybe there is a way to get more information about this exception somehow, but… for the sake of this blog posting, let’s assume that it actually is impossible. :-)

    It is my impression that sometimes (for some odd reason…) the real error message is “hidden” within the WCF layer. But, luckily for us, there is an easy way to poke around in the actual communication between the WCF client and the server. Its name is Fiddler, and it’s actually a freeware tool developed by a Microsoft employee. Fiddler works as an HTTP proxy, letting you intercept the traffic between any HTTP client and server (this includes WCF, if you are using one of the http binding types as the binding for your WCF client, which is often the case). When the program is started, it automatically takes over all traffic from most HTTP clients on your client machine (including WCF clients and Internet Explorer). It does so by modifying the the Internet Explorer proxy settings. When Fiddler is closed, it automatically changes the proxy settings back for you, so it’s very convenient to use in that sense.

    Here is what the program looks like when you start it up:

    Fiddler1

    As you see, Fiddler itself has performed an update check to see if any new version of the program is available. If you click this line in the Web Sessions list, you are able to inspect how this specific request/response looked.

    Now, let’s get back to our real-world debugging scenario. We assume that the client has run, and the illegal operation above has been performed. This is what our Fiddler console looks like now.

    Fiddler2

    As you see, even Fiddler itself realizes there something wrong with this request. I guess this is because of the HTTP 500 result code that was sent by the server (HTTP result code 500 means “Internal Server Error”). Let’s click this red-marked row:

    Fiddler3

    We are now shown some basic information about the session, which we are not very interested in right now but which could be more interesting if you were size-optimizing a web site (or just checking how heavy it would be to load over different kind of Internet connections/geographic locations). Let’s open the Inspectors tab (marked with red above).

     Fiddler4

    We are now shown an overview of the HTTP headers involved in this request. Still, we are not getting really what we where aiming for. Let’s open the TextView for both the request and the response (marked with red above).

    Fiddler5

    Now we’re talking! Quite a lot more useful than the “NotFound” error we got earlier. A stack trace is always a lot more useful; as you see, we can even see the line number in the source code file where the error appeared, giving us the opportunity to debug the server and place a breakpoint there (for example).

    Well, that’s basically it. In this blog posting, you have been introduced to a WCF scenario where no real clue was found in the exception details as to what the real problem was. You’ve learned the basic concepts of how Fiddler works, and how you can use it to debug WCF services (and web services, and really any kind of web-related scenario – web browsing, AJAX, you name it…). For those of you who already very skilled in these areas, too bad; you may not have learned very much from this. But relax, take it easy, I’ll write about something more technically challenging some other time. I promise. :-)