Category Archives: ASP.NET

Compressing ASPX pages with IIS

GZip / DEFLATE compression’s a quick and simple trick you can employ to reduce the size of your pages that get sent down the wire. IIS supports this natively (IIS5 & IIS6, the latter improving the process somewhat). The best part is that it’s quick simple to get up and running.

Jump onto the box you run IIS in as admin, open up a new cmd, and punch away the following:

go to your InetPubadminscripts directory

net stop iisadmin   //To stop the services

cscript adsutil.vbs set W3Svc/Filters/Compression/GZIP/HcScriptFileExtensions  “aspx” “asp” “dll”  //Register the additional types to compress

net start w3svc   //Start the services back up

This sort of technology has been around for a while, so only users running on the most outdated browsers might have a few issues. But for the rest of us, compression can significantly reduce download times. For instance a Reporting Services report would come down as 500KB uncompressed, but only 50KB when compressed with GZip. That’s 10% of the original.

That’s quite significant when you’re looking at slow connections, and the additional CPU load/time to compress is irrelevant when compared to savings in the download time side of things.

A quick side note is that there’s hardly any difference between GZip and DEFLATE compression technologies. They’ll both give you pretty much the same ratio’s, but from memory DEFLATE contains a number of additional header fields, hence will be a number of bytes larger than its GZip counterpart.

Automatic Bug Reporting in Global.asax

One thing I really like about .NET is the flexibility and speed it gives you to implement new functionality. By using ASP.NET’s Global.asax file, you can very easily hook into any major application events that occur in your system. Perhaps one of the most useful of these is the Application_Error event, which fires everytime an unhandled exception occurs within your site. During your testing phase, this can be a very useful place to find out how your users are experiencing your stystem.

One of the projects I’m working on has just gone back to the stakeholders and users, who are now trying out the functionality to see if there’s anything they’ve left out. With the test team working off the same copy, there’s a good number of people accessing the system. When stuff breaks, it’s critical you find out why. Some users are good and will cut & paste you the exception + stacktrace, some will go better and add the URL or tell you the page they were on, and I’m still waiting on those who will go through a step-by-step process to recreate the error – but you can always wish.

Instead of relying on the user to remember to log the bug or tell the dev team about such blaring issues, I figured it would be more reliable to get the system to log its own bugs. Here’s a way to edit your Global.asax so that it will email you back such exceptions:

void Application_Error(object sender, EventArgs e)

{

    // Code that runs when an unhandled error occurs

    Exception ex = Server.GetLastError().GetBaseException();

    string user = HttpContext.Current.User.Identity.Name;

    string url = HttpContext.Current.Request.Url.ToString();

 

    //Emails the exception to me  

    System.Net.Mail.MailMessage mail = new System.Net.Mail.MailMessage(

        [email protected],

        “adenhertog”,

        “BUG: PROJECT- “ + ex.Message,

        string.Format(“For user: {0}nAt: {1}n{2}”, user, url, ex.StackTrace));

 

    System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(“smtp.server”);

    client.Send(mail);

}

This is Ok for small projects, but more often or not you’ll be using a bug tracking system of some sort. We run Bugzilla where I am, which exposes web services (XMLRPC) that ultimately can be used in conjunction with the Global.asax code to get the system to log its own bugs.

If your bug tracking system supports web services, or even if it runs off a database, by modifying the Application_Error code, you too can ensure that bugs don’t go unreported.

 

How not to use ASP.AJAX – Pt 4

Previously I’ve spoken about how the ASP.NET Ajax can be used and abused. It offers a very quick and simple framework to make parts of your webpage asynchronous, mainly through use of the UpdatePanel. The tradeoff is the responsiveness of your site, and the fact that the Viewstate needs to be passed with every call. A way around the ASP.NET Ajax bloat is to use Json, which provides simple and lightweight communication with the server, at the cost of a little more complexity and loss of maintainability.

A common scenario in using ASP.NET Ajax is to put a GridView or other data based control into an update panel, with a Timer to continually poll the data. This would look something like:

<asp:UpdatePanel runat=”server”>

    <ContentTemplate>

        <asp:GridView runat=”server” DataSource=”dsSales” />

        <asp:Timer runat=”server” Interval=”5000″ />

    </ContentTemplate>

</asp:UpdatePanel>

This is a grid that would get updated every 5 seconds.

Unfortunately, if you had 3 of these suckers on the page, or if the data source gets updated sporadically, you’re going to see a big viewstate being handed back and forth every 5 seconds. Consider this chunk of HTML:

<asp:UpdatePanel runat=”server” ID=”upSalesWest”>

    <ContentTemplate>

        <asp:GridView ID=”gvSalesWest” runat=”server” />

        <asp:Timer ID=”timSalesWest” runat=”server” Interval=”5000″ />

    </ContentTemplate>

</asp:UpdatePanel>

 

<asp:UpdatePanel runat=”server” ID=”upSalesEast”>

    <ContentTemplate>

        <asp:GridView ID=”gvSalesEast” runat=”server” />

        <asp:Timer ID=”timSalesEast” runat=”server” Interval=”5000″ />

    </ContentTemplate>

</asp:UpdatePanel>

 

<asp:UpdatePanel runat=”server” ID=”upSalesNorth”>

    <ContentTemplate>

        <asp:GridView ID=”gvSalesNorth” runat=”server” />

        <asp:Timer ID=”timSalesNorth” runat=”server” Interval=”5000″ />

    </ContentTemplate>

</asp:UpdatePanel>

The viewstate is not small. As such, you want to reduce the number of ASP.NET Ajax calls as best you can. So what can you do? Firstly, get rid of all those Timers. If you’re checking for a batch of updates, you only really want to use one call. You can do this using a single call to a web service that returns the update “triggers” so to speak, that are held within the update panels:

[WebMethod]

public string[] GetUpdatedGrids()

{

    //(Based on your data sources)

    //Check the datasources bound to gvSalesWest, gvSalesEast, gvsSalesNorth

    //to see which ones contain “dirty” data (ie: which ones have

    //been updated since the data was last checked

 

    //txtSalesEast, txtSalesNorth etc are textboxes within the update panels

    //They are hidden through CSS, and automatically post back when their

    //value changes, which will cause the update of the UpdatePanel they’re in

    //Unfortunately this is a hacky way to get UpdatePanels to update via javascript,

    //until MS releases something more capable.

    return new string[] { “txtSalesEast”, “txtSalesNorth” };

}

To call the webservice on a timed basis, all you need to do is take advantage of javascript’s SetInterval(delegate, n) function, which executes a given function every n milliseconds. With the new TextBox triggers, your modified HTML will look like:

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head runat=”server”>

    <title>Timer Demo</title>

    <script type=”text/javascript”>

        function StartTimer()

        {

            SetInterval(GetUpdatedGrids, 5000);

        }

 

        function GetUpdatedGrids(result)

        {

            for(var i=0; i<result.length; i++)

                RefreshPanel(result[i]);

        }

 

        function RefreshPanel(triggerName)

        {

            //Changing the value of the textbox trigger will cause it to postback and

            //update its parent UpdatePanel

            document.getElementById(triggerName).value = new Date().getTime();

        }

    </script>

</head>

<body onload=”StartTimer()”>

    <form id=”form1″ runat=”server”>

        <asp:ScriptManager ID=”ScriptManager1″ runat=”server” >

            <Services>

                <asp:ServiceReference Path=”WebService.asmx” />

            </Services>

        </asp:ScriptManager>

        <div>

            <asp:UpdatePanel runat=”server” ID=”upSalesWest”>

                <ContentTemplate>

                    <asp:GridView ID=”gvSalesWest” runat=”server” />

                    <asp:TextBox runat=”server” ID=”txtSalesWest” AutoPostBack=”true” style=”display:none;” />

                </ContentTemplate>

            </asp:UpdatePanel>

 

            <asp:UpdatePanel runat=”server” ID=”upSalesEast”>

                <ContentTemplate>

                    <asp:GridView ID=”gvSalesEast” runat=”server” />

                    <asp:TextBox runat=”server” ID=”txtSalesEast” AutoPostBack=”true” style=”display:none;” />

                </ContentTemplate>

            </asp:UpdatePanel>

 

            <asp:UpdatePanel runat=”server” ID=”upSalesNorth”>

                <ContentTemplate>

                    <asp:GridView ID=”gvSalesNorth” runat=”server” />

                    <asp:TextBox runat=”server” ID=”txtSalesNorth” AutoPostBack=”true” style=”display:none;” />

                </ContentTemplate>

            </asp:UpdatePanel>

        </div>

    </form>

</body>

</html>

One thing to note specific to this example is that it would probably want to throw a js error on RefreshPanel(), as the triggerName parameter passed to it is the ID of the control, rather than the ClientID

The whole point of this design is to use the heavy duty ASP.NET Ajax calls only to update the data. In the interim, we use lightweight Json calls to see if anything has actually been updated. For data that gets updated “every now and then”, this model helps eliminate more bandwidth intensive calls through ASP.NET Ajax, which ultimately could all be for no purpose if the underlying data is still the same.

From the past few posts, I’ve demonstrated how we can implement Json and Web.Services as an alternative to ASP.NET Ajax, and lastly how they can work side-by-side. As I’ve mentioned in the past, sometimes one method is superior to the other, but that’s the fun of IT – it’s your call as to which one you feel is best to use.

How not to use ASP.AJAX – Pt 3

In JSON, passing objects from javascript to .net web services is a cinch. In fact, it’s easier by far than doing it in the old Xml notation.

In my last post I spoke about how you can reduce the bloat of your apps by not being so reliant on the ASP.NET AJAX implementation, and going with lightweight JSON calls. In the example, I was passing string values around as parameters and return values which worked quite well.

However oftentimes you’ll want to be moving around your own objects and other complex types, and converting these objects back to their primitive types on each method is something that would drive you nuts.

Fortunately both the javascript and .net frameworks provide a way of doing these things for us, without us having to write even a single line of code.

First, let’s create a web service that returns us a fictional instance of a Person class called ‘Gary’:

using System;

using System.Web;

using System.Collections;

using System.Collections.Generic;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Web.Script;

using System.Web.Script.Services;

 

namespace MyAjax

{

    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    [ScriptService]

    public class WebService : System.Web.Services.WebService

    {

        [WebMethod]

        public Person GetPerson()

        {

            Person gary = new Person();

            gary.Firstname = “Gary”;

            gary.Lastname = “Familyman”;

            gary.Age = 42;

 

            Person wife = new Person();

            wife.Firstname = “Betty”;

            wife.Lastname = “Familyman”;

            wife.Age = 40;

 

            Person daughter = new Person();

            daughter.Firstname = “Sabrina”;

            daughter.Lastname = “Familyman”;

            daughter.Age = 10;

 

            Person son = new Person();

            son.Firstname = “Mike”;

            son.Lastname = “Familyman”;

            son.Age = 12;

 

            gary.Relatives.Add(“wife”, wife);

            gary.Relatives.Add(“daughter”, daughter);

            gary.Relatives.Add(“son”, son);

 

            return gary;

        }

    }

 

    public class Person

    {

        private string firstname;

        private string lastname;

        private int age;

        private Dictionary <string, Person> relatives;

 

        public Person()

        {

            relatives = new Dictionary<string, Person>();

        }

 

        public string Firstname

        {

            get { return firstname; }

            set { firstname = value; }

        }

 

        public string Lastname

        {

            get { return lastname; }

            set { lastname = value; }

        }

 

        public int Age

        {

            get { return age; }

            set { age = value; }

        } 

 

        public Dictionary<string, Person> Relatives

        {

            get { return relatives; }

        }

    }

}

Essentially we create Gary, and a few of his family members. The purpose here is to create a complex type – you wouldn’t actually want to create people in this way!

We create the service as a script service so it’s accessible via the javascript in our page. Calling the web service method then becomes a breeze:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head runat=”server”>

    <title>Untitled Page</title>

    <script type=”text/javascript”>

        function GetGary()

        {

            MyAjax.WebService.GetPerson(

            function(result)

            {

                var setBreakpoint;

            });

        }

 

    </script>

</head>

<body>

    <form id=”form1″ runat=”server”>

        <asp:ScriptManager ID=”ScriptManager1″ runat=”server” >

            <Services>

                <asp:ServiceReference Path=”WebService.asmx” />

            </Services>

        </asp:ScriptManager>

        <div>

            <a href=”javascript:GetGary();”>Tell me about Gary</a>

        </div>

    </form>

</body>

</html>

I’m using Firefox with the Firebug plugin installed. I’ve found this to be one of the best javascript debuggers out there, and it’s not as fiddly to use as the one built into visual studio. I simply set a breakpoint on the var setBreakpoint; line, click the link in the browser, and my result value looks like this:

How easy is that? This means that to get attributes associated with “Gary” in the javascript, I just need to write code like:

result.Firstname //”Gary”;

result.Age // 42

result.Relatives.daughter.Firstname // “Sabrina”

and so on!

Oh, and the other thing is too, don’t worry about the bloat on the wire. Because this doesn’t use server controls, the only data being set back and forth is going to be related soley to your objects. To illustrate the point, “Gary” the Person object comes back as:

Response

{“__type”:”MyAjax.Person”,”Firstname”:”Gary”,”Lastname”:”Familyman”,”Age”:42,”Relatives”:{“wife”:{“__type”:”MyAjax.Person”,”Firstname”:”Betty”,”Lastname”:”Familyman”,”Age”:40,”Relatives”:{}},”daughter”:{“__type”:”MyAjax.Person”,”Firstname”:”Sabrina”,”Lastname”:”Familyman”,”Age”:10,”Relatives”:{}},”son”:{“__type”:”MyAjax.Person”,”Firstname”:”Mike”,”Lastname”:”Familyman”,”Age”:12,”Relatives”:{}}}}

Which really is as terse and succinct as you can get.

Passing objects around in JSON / ASP.NET AJAX is just as easy as passing primitive types. The advantage is that you don’t need to send the viewstate or any other information, hence can achieve far superior speed and efficiency gains in your web application.

How not to use ASP.AJAX – Pt 2

In my last post, I touched on the bloat that ASP.NET AJAX adds to your site, and ways of reducing the viewstate overhead for asynchronous calls.

This time round, I want to speak more about JSON and Web Services.

JSON (JavaScript Object Notation) is an extremely lightweight data structure that Web Services built in .NET can understand and interpret. Web Services are typically associated with XML calls, which although are verbose and readable, aren’t much fun to create in Javascript and often end up hogging all your bandwidth.

JSON gets compressed into a single string, which gets passed to your web service that then constructs that string back into an object. For those living with in .NET 3.0 land out there, JSON is very similar to Object Initialisers.

So now we have a lightweight object notation that can communicate with Web Services built in .NET. Great. But how can we leverage these technologies to reduce the bloat of ASP.NET AJAX?

This all comes down to your architecture and how your pages get used. If you put a DataGrid within an UpdatePanel to achieve asynchronous everything, it’s going to be difficult to replace that functionality with JSON and Web Service calls.

However, if you have a couple of text boxes and a submit button within an UpdatePanel that sends the text box values off to the server, chances are you can replace this with a JSON implementation. Consider this basic scenario:

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head runat=”server”>

    <title>Ajax Example</title>

<script runat=”Server” language=”C#”>

    protected void lnkSubmit_Click(object sender, EventArgs e)

    {

        lblGreeting.Text = string.Format(“Welcome: {0} {1}”, txtFirstname.Text, txtLastname.Text);

        pnlInput.Visible = false;

        pnlOutput.Visible = true;

    }

</script>

</head>

<body>

    <form id=”frmMain” runat=”server”>

    <asp:ScriptManager runat=”server” />

    <div>

        <asp:UpdatePanel runat=”Server” ID=”upGreetMe”>

            <ContentTemplate>

                <asp:Panel runat=”server” ID=”pnlInput” DefaultButton=”lnkSubmit”>

                    Firstname: <asp:TextBox runat=”server” ID=”txtFirstname”></asp:TextBox><br />

                    Lastname: <asp:TextBox runat=”server” ID=”txtLastname”></asp:TextBox><br />

                    <asp:LinkButton runat=”server” ID=”lnkSubmit” Text=”Submit” OnClick=”lnkSubmit_Click” />

                </asp:Panel>

                <asp:Panel runat=”Server” ID=”pnlOutput” Visible=”False”>

                    <asp:Label runat=”server” ID=”lblGreeting” />

                </asp:Panel>

            </ContentTemplate>

        </asp:UpdatePanel>   

    </div>

    </form>

</body>

</html>

Which would give something like the following:

That’s an easy implementation, but how does it look on the wire?

Request:

ctl02=upGreetMe|lnkSubmit&__EVENTTARGET=lnkSubmit&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwUKMjA3OTY1ODc0N2RkcEMKQ
DsHztIsqEaftQkNhQqa9L8%3D&txtFirstname=Andrew&txtLastname=den%20Hertog&__EVENTVALIDATION=%2FwEWBAKev73aCwLZh62
pDwKdlcWkAgKg%2BLK0C8JDoC%2F8jw%2BvvB1lvzQCJ%2B0MXZCK&

Response:

cc

177|updatePanel|upGreetMe|

               

                <div id=”pnlOutput”>

 

                    <span id=”lblGreeting”>Welcome: Andrew den Hertog</span>

               

</div>

            |

1d8

228|hiddenField|__VIEWSTATE|/wEPDwUKMjA3OTY1ODc0Nw9kFgICAw9kFgICAw9kFgJmD2QWBAIBDw8WAh4HVmlzaWJsZWhkFgQCAQ8PFg
IeBFRleHQFBkFuZHJld2RkAgMPDxYCHwEFCmRlbiBIZXJ0b2dkZAIDDw8WAh8AZ2QWAgIBDw8WAh8BBRpXZWxjb21lOiBBbmRyZXcgZGVuIEhl
cnRvZ2RkZD1YbZtEvITGhXSRS3Xr2lM4dxyZ|0|asyncPostBackControlIDs|||0|postBackControlIDs|||10|updatePanelIDs||tup
GreetMe|0|childUpdatePanelIDs|||9|panelsToRefreshIDs||upGreetMe|2|asyncPostBackTimeout||90|9|formAction||test.
aspx|12|pageTitle||Ajax Example|

0

So for the most basic of calls, with NO other controls on the screen at all, you’re still looking at a round trip payload of 274 upstream + 668 downstream = 942 bytes. Might not seem like much yet, but once you put more controls on your screen, that sucker’s going to get big.

Achieving this in JSON is a bit more involved, but not impossible.

First thing you need to do is to create a webservice, call it WebService.asmx. It should look something like this:

using System;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Web.Script.Services;

 

namespace MyAjax

{

    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    [ScriptService]

    public class WebService : System.Web.Services.WebService

    {

        [WebMethod]

        public string Greet(string firstname, string lastname)

        {

            return string.Format(“Welcome: {0} {1}”, firstname, lastname);

        }

    }

}

Next thing is we need to overhaul the original web page so that it only uses web service method calls:

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head runat=”server”>

    <title>Ajax Example</title>

<script type=”text/javascript”>

    function lnkSubmit_Click()

    {

        var firstname = document.getElementById(“txtFirstname”).value;

        var lastname = document.getElementById(“txtLastname”).value;

        MyAjax.WebService.Greet(

            firstname,

            lastname,

            function(returnVal)

            {

                var inputPanel = document.getElementById(“pnlInput”);

                var outputPanel = document.getElementById(“pnlOutput”);

 

                inputPanel.style.display = ‘none’;

                outputPanel.style.display = ‘block’;

 

                document.getElementById(“pnlOutput”).innerHTML = returnVal;

            });

    }

</script>

</head>

<body>

    <form id=”frmMain” runat=”server”>

    <asp:ScriptManager runat=”server” >

        <Services>

            <asp:ServiceReference Path=”WebService.asmx” />

        </Services>

    </asp:ScriptManager>

    <div>

        <div id=”pnlInput”>

            Firstname: <input type=”text” id=”txtFirstname” /><br />

            Lastname: <input type=”text” id=”txtLastname” /><br />

            <a href=”javascript:lnkSubmit_Click()” id=”lnkSubmit”>Submit</a>

        </div>

        <div id=”pnlOutput” style=”display:none;”></div>

    </div>

    </form>

</body>

</html>

To explain the code, we’ve blown away the update panels, converted the regular panels to divs, and got rid of all server controls.

The script manager on the page has a ServiceReference to WebService.asmx, which creates the javascript function MyAjax.WebService.Greet() which makes calls to the Web Service very simple. For this to work, you need to ensure that your web service contains the attribute [ScriptService]

The hiding and showing of divs is simple javascript/css manipulation.

You’ll notice when I call the Web Service method Greet(string, string) I’m passing three parameters. The third parameter is a delegate which gets executed on a successful round trip, with the return value held in returnVal.

This seems like a lot of work, but lets see what the benefits are in terms of our network usage:

Request:

{“firstname”:”Andrew”,”lastname”:”den Hertog”}

Response:

“Welcome: Andrew den Hertog”

That’s a roundtrip of upstream 46 + downstream 26 = 72bytes in total. That’s just 7% of the overhead from the original model. Furthermore if you added more server controls to the page, this method will always just return 72bytes, whereas the ASP.NET AJAX implementation will grow and bloat to accomodate the viewstate.

To reiterate, ASP.NET AJAX is very easy to work with, but it does add significant overhead to your system. Using JSON and Web Services where possible will speed up your site, but perhaps at the loss of code maintainability and site complexity. It’s your call to see where you should and shouldn’t change your approach, but the more you can do to reduce your network usage, the fast your site will appear and the happier the end user will be.

How not to use ASP.AJAX – Pt 1

I’ve worked with ASP.NET AJAX long enough now to appreciate both the increases in productivity on the development side, whilst also discovering the significant bloat it adds to sites where it’s implemented. In light of this, I’ve decided to put up a number of posts on how you can reduce the dependancy your sites have on this model.

On the development side of things, the ASP.NET AJAX model is fantastic. Any part of your site that you want working asynchronously you just drop inside an UpdatePanel and you’re away. You don’t need to code nor maintain any javascript, it’s simply plug & play.

However with this convenience comes a lot of overhead. Not only do visitors to your site have a significant initial download to get all the javascript libraries, each call from a control or trigger for an UpdatePanel will then cause the entire viewstate for that page to be sent to the server, and a new one returned. This is where things can get out of hand.

For small sites with a limited number of sever controls on a page, the viewstate can be quite small and hence this isn’t an issue. However as the size and scale of your site increases, it’s almost inevitable that more server controls will be added to your page, increasing the viewstate size, and each subsequent postback to the server.

To check out exactly what and how much is being sent back and forth between your browser and your web server, I highly recommend an HTTP logger such as the likes of Fiddler 2 by Eric Lawrence. This will let you see the raw output of everything that gets sent between your browser & server.

Now, lets take your site into account that uses the ASP.NET AJAX model, what’s the first thing you can do to improve the efficiency of your site?

The obvious answer to this is to reduce the number of server controls you have on your site. A common mistake is to use labels as containers for static text. When you add a label to your site, it inevitably gets turned into a <span></span> block, with the additional overhead of increasing the viewstate size. For this reason, you should aim to convert as many of your labels into <span></span> blocks as you can.

But what if the text for the label is set dynamically? You can still use server-side scripting within your HTML. Take for instance a simple “Welcome <Name>” label. In your page source it looks something like:

<asp:Label runat=”server” ID=”lblWelcome”></asp:Label>

and your code behind:

lblWelcome.Text = string.Format(“Welcome: {0} {1}”, Global.User.Firstname, Global.User.Surname);

On the client side, it will turn up as:

<span id=”lblWelcome”>Welcome: Andrew den Hertog</span>

with our viewstate going from:

/wEPDwUJNzgzNDMwNTMzZGRAXRyhyf+YSOvbHZfmj+wHXiuDGg==

to

/wEPDwUJODExMDE5NzY5D2QWAgIDD2QWAgIBDw8WAh4EVGV4dAUaV2VsY29tZTogQW5kcmV3IGRlbiBIZXJ0b2dkZGS52vt7OHtVWwBQyWufRS3o2gv/LQ==

It’s not so bad right? I mean this has only increased the viewstate by a little bit. But what happens if we had lots of labels? Or even just had heaps of text pouring into one?

lblWelcome.Text = “”.PadLeft(1000, ‘a’);

Our viewstate turns into a monster:

/wEPDwUJODExMDE5NzY5D2QWAgIDD2QWAgIBDw8WAh4EVGV4dAXoB2FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFkZGQrwjhWv3Cqncvs3Zebq60sXhc/Ug==

The far better option in either case is to plant the text directly into your HTML to prevent it being added to your viewstate:

<span id=”lblWelcome”><%=string.Format(“Welcome: {0} {1}”, Global.User.Firstname, Global.User.Surname) %></span>

Viewstate:

/wEPDwUJOTU4MjMyMzI1ZGTGMsJAGEAyzW+ZLZ++DQd01dNucA==

That’s far more economical.

It’s almost impossible to eliminate all of the server controls for your page, however reducing them can significantly subtract from the viewstate overhead you incur. Now remembering that for every ASP.NET AJAX call you make you send back the viewstate. This viewstate includes the state of ALL the controls on the page, not just the ones inside your UpdatePanel. By reducing the number of server controls on your page, you can potentially stand to gain some significant bandwidth reductions and subsequent performance increases on your site.

Localisation / Localization in C# ASP.NET

Localisation is something that naturally forms the part of a websites life as it grows & develops. With things like language packs, currency & date formats specific to a user’s locale, a site can reach a far wider audience than it could using the standard en-us interface. 

However it’s not just for those of us who want to make a localised site. You can (and should) also use this method to replace the text for all your labels on your site. This way, you further split out the design from the code of your website. 

.NET makes this process very easy indeed, and with a little bit of forward planning today, you can save yourself an expensive redevelopment task in the future to get your site working across borders. 

Localising your site based on the method I’m going to describe has a number of failsafe features: 

  • If the key doesn’t exist in your resource file, then it will return the key as the value. Hence if you send down “Welcome to my site” as the key, which isn’t found, it will then render this as the value.
  • If the resource file doesn’t exist for the locale of the user, the system will default to the fallback resx defined in the Translate.message class.
  • Once implemented, you can simply add more resx’s to the resource project (ie support more languages), without having to write a single additional line of code!

In this example, I’m going to use the following locales: 

  • en-au (Australian English – my corner of the world)
  • zh-cn (PRC Chinese – what I’ve been studying for a few years)

This example also follows on in a sense from yesterday’s article on Embedded Web Resources, where we’ll be putting our language files inside a dll for safe keeping.  

The first thing you need to do is create two new resource files, embedding them in the resources dll, named according to their contents, ie: 

  • en-au.resx
  • zh-cn.resx

Resource files are simply an Xml file containing three columns – Name, Value and Comment. It pretty much acts like a Dictionary, where you have a Key field (Name), a Value field, but also a comment field should you feel the need to be a proactive documenter. 

Add a few entries your resource files. Mine ended up looking like this: 

 

As with most things code, making things simple & easy is the key. So you want to have a look at a quick way to retrieve values out of these resource files. 

The first thing you want to do on your website is determine what language the user’s browsing in. To do this, I’m going to create a “Translate.cs” class in my resources dll, and add the following: 

 

public static class Translate 

    public static string GetLanguage() 

    { 

        return HttpContext.Current.Request.UserLanguages[0]; 

    } 

  

    public static string Message(string key) 

    { 

        ResourceManager resMan = null

        if (HttpContext.Current.Cache["resMan" + Global.GetLanguage()] == null

        { 

            resMan = Language.GetResourceManager(Global.GetLanguage()); 

            if (resMan != null) HttpContext.Current.Cache["resMan" + Global.GetLanguage()] = resMan; 

        } 

        else 

            resMan = (ResourceManager)HttpContext.Current.Cache["resMan" + Global.GetLanguage()]; 

  

        if (resMan == null) return key; 

  

        string originalKey = key; 

        key = Regex.Replace(key, “[ ./]“, “_”); 

  

        try 

        { 

            string value = resMan.GetString(key); 

            if (value != null) return value; 

            return originalKey; 

        } 

        catch (MissingManifestResourceException

        { 

            try 

            { 

                return HttpContext.GetGlobalResourceObject(“en_au”, key).ToString(); 

            } 

            catch (MissingManifestResourceException mmre) 

            { 

                throw new System.IO.FileNotFoundException(“Could not locate the en_au.resx resource file. This is the default language pack, and needs to exist within the Resources project.”, mmre); 

            } 

            catch (NullReferenceException

            { 

                return originalKey; 

            } 

        } 

        catch (NullReferenceException

        { 

            return originalKey; 

        } 

    } 

  

This is actually a pretty simple class. GetLanguage() does just that – gets the locale code of the language the user is browsing in (eg: “en-us”, “en-au” etc). The Message function simply accepts a string, which lines up to the “Name” column within your .resx files (note that in the resx files, the name cant contain spaces, dots or forward-slashes, so I replace them with underscores in this example). 

This also makes use of the Language class, which is home-brewed and sits in the same location as your resx files: 

public static class Language 

    public static List<string> GetSupportedLanguages() 

    { 

        HttpContext context = HttpContext.Current; 

        if (context != null

            if (context.Cache["SupportedLanguages"] != null

                return context.Cache["SupportedLanguages"] as List<string>; 

  

        string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames(); 

        List<string> languages = new List<string>(); 

  

        for (int i = 0; i < names.Length; i++) 

            if (Path.GetExtension(names[i]).Equals(“.resources”, StringComparison.OrdinalIgnoreCase)) 

                languages.Add(Path.GetFileNameWithoutExtension(names[i])); 

  

        if(context != null) context.Cache["SupportedLanguages"] = languages; 

        return languages; 

    } 

  

    public static ResourceManager GetResourceManager(string languageCode) 

    { 

        foreach (string name in GetSupportedLanguages()) 

        { 

            string[] arrLanguageCode = name.Split(‘.’); 

            string supportedLanuageCode = arrLanguageCode[arrLanguageCode.Length - 1]; 

  

            if (supportedLanuageCode.Equals(languageCode, StringComparison.OrdinalIgnoreCase)) 

            { 

                ResourceManager resMan = new ResourceManager(name, Assembly.GetExecutingAssembly()); 

                return resMan; 

            } 

        } 

        return null

    } 

  

 

GetSupportedLanguages() uses reflections to pull your resx files out of the resources dll. GetResourceManager() returns a ResourceManager, which is essentially the C# interface to those resource files. 

The final step is really just a simple operation to thread your resource files into your interface. So before where you might have had: 

<span class=”label”>User:</span>  

You now would put: 

<span class=”label”><%=Translate.Message(“User”) %>:</span>  

When it comes time to render the document, the web server sends the key “User” to the Translate.Message function, which looks it up in the resource file that matches the user language, and then puts in the text held in the “Value” column of that resource file. 

Thus far, this is the best I can come up with for getting multiple languages across your interface, as it provides a very pluggable interface for maintaining language packs. You can adapt this methodology to work easily with Winform applications. 

Localising your site from the beginning will save you a lot of time refactoring your code in the future, and also split out the text of your interface (which essentially should be treated as data, rather than structure / code). Localisation also builds in a lot of movement for growth in your site, and goes a long way towards customising a site per-user. 

Embedded Web Resources

If, as an ASP.NET developer, you haven’t used embedded resources, you’re missing out big. 

How many times have you had to deploy or maintain a site, only to have one or more of your images going missing, javascripts being modified by rogue web admins, or wrestling with the ASPNET securities monster? 

If the answer’s more than one, or even if it’s zero, you need to think about embedding your site’s resources at some point. The basic idea is that you embed your sites resources (ie, javascript, images, EULAs or whatever you have) into a seperate class library. When a resource is then requested by the user, the web server then pulls the requested resource out of the dll rather than the filesystem. 

The nice part is it’s pretty simple to do. There are really just 2 main parts – get the resources into the dll, get the resouces out of the dll. 

Firstly you need to create a new class library that’s referenced by your web project. Be sure to give it a default namespace, something like <Company>.<Project>.Resources is a good start. 

Add to it your resources 

 

Next, select all your resources, go to their property page (F4), and set their build action to “Embedded Resource”. This means that when you go to compile your DLL, your “Embedded resource” files will be stored inside it. 

The next step is an easy one to forget. Although the resources have been embedded, you need to mark them to be accessable as a web resource. To do this you need to open up your PropertiesAssemblyInfo.cs and add the following line for each one of your resources

[assembly: WebResource("Company.Project.Resources.Images.Login.background.gif", "image/gif")] 

The file reference is made up of Namespace.Folder(s).filename.ext 

Compile your project to produce the dll. I highly recommend Lutz Roeder’s .NET Reflector – a functional and free dll browser, essential to any .NET dev’s toolkit. You can use this to see 

  1. if your files are being embedded in the dll, and
  2. what their manifest names are

To get the resources out of the dll, you need to use the method call: 

Page.ClientScript.GetWebResourceUrl(typeof(Language), “Company.Project.Resources.Images.Login.background.gif”); 

For simplicity sake in my site, I’ve created a public static class to do this stuff for me, and also take out the repetitiveness of having to supply the same namespace all the time: 

 

public static class Global 

    public static string GetResource(Page currentPage, string resourceName) 

    { 

        string resNamespace = typeof(Language).Namespace; 

        return currentPage.ClientScript.GetWebResourceUrl(typeof(Language), resNamespace + “.” + resourceName); 

    } 

 

In the above examples, Language is simply a class that i’ve compiled into the Resources dll. It’s necessary so that reflections can locate the assembly that contains your resources. This method will return a string that looks something like this: 

WebResource.axd?d=rLxM_e-hNRgcxNZLXGjctTk29lCIdmt5WI7DIzX8eu0chQcXvXKMdywK0qPrNmD7OWHAxEdM_Bgznu_OY1JLU413x9VqlXs-NmZ294HGH8E1&t=633300286780182866 

So for instance to display the background image, in your HTML you’d use: 

<img src=”<%=Global.GetResource(Page, “Images.Login.background.gif”) %> alt=”Login Background” /> 

And there you have it, your images should then be read through your dll and viewable through your web browser. You can do the same with your javascripts, or really any other static file. You can then deploy websites which don’t have a whole heap of images that can go missing. But a word of warning – because you’re embedding all these things into a single dll, it gets fully loaded into memory. Making it too big will impact the performance of your website. 

For this reason, here’s a quick list of DOs and DONTs: 

DO 

  • Embed frequently used resources
  • Embed javascripts etc that you don’t want sneaky web admins to modify
  • Files that tend to remain static throughout the life of your server

DONT 

  • Embed big media (ie: video, audio, swf’s, streaming data)
  • Embed files which are rarely accessed
  • Embed files which need to be writable