Wednesday, May 25, 2005

Disable Validators on the Client

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/disable_validators_on_the_client.htm]

Sometimes you may want client-side activities to disable a validator. For example, suppose a TextBox is only required if a CheckBox is selected. The TextBox could have a RequiredValidator, but we'd like selecting the CheckBox to enable/disable that validator at the client.

One approach is to use JavaScript functions from the WebUIValidation.js file located at: aspnet_client\system_web\1_1_4322. This stores the script used by ASP.Net's validators and is available to all pages. It includes a script, ValidatorEnable, which takes a control and a boolean and sets the control's Enabled property to the boolean value.

For example, you could have the onclick of a checkbox (id=ChkEnable), call the custom javascript below.

function EnableValidator() {
    var blnEnabled = document.Form1.ChkEnable.checked;
    ValidatorEnable(document.getElementById("RequiredFieldValidator1"),blnEnabled);
}

We still need to persist these changes to the server. We can simply enable/disable the validator in the page load:

this.RequiredFieldValidator1.Enabled = this.ChkEnable.Checked;

In summary, ASP.Net provides easy ways to disable a validator based on client activity. This lets us extend the default validator functionality.

Monday, May 23, 2005

Debugging JavaScript in Visual Studio

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/debugging_javascript_in_visual_studio.htm]

Everyone knows that you can use Visual Studio to debug Class Libraries, such as server-side WebForms. However, you can also use it to debug client-side JavaScript. I've seen some developers who don't realize this because they open up the JS as if it were a class file, add the breakpoint, run the application, and never see the breakpoint hit.

You need to first enable script debugging in your browser (list quoted from MSDN):

  1. In Internet Explorer, click the Tools menu and choose Internet Options.
  2. Click the Advanced tab.
  3. Under the Browsing category, clear the Disable Script Debugging checkbox.

Then any JS file will appear in the Running Documents window. You can open the file from there, add the breakpoint, and step through the script.

Thursday, May 19, 2005

Improving Application Performance by Implementing Paginated Lists

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/improving_application_performance_by_implementing_paginated_lists.htm]

I left CSC and joined Ameripay this week as a Software Engineer. Ameripay is America's leading independent provider of payroll and human resource solutions. While CSC is a great consulting company, I'm excited about the stability (i.e. lack of travel) of e-commerce here. Our dev manager, Chuck Cooper, recently published an article on MSDN: Improving Application Performance by Implementing Paginated Lists.

Most enterprise applications need to page through large sets of data. It's easy to implement this with bad performance. Chuck's article offers high performance ways to handle this, and is a good read.

Wednesday, May 11, 2005

Improving .Net Application Performance and Scalability

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/improving_net_application_performance_and_scalability.htm]

I've been reading a great book, Improving .Net Application Performance and Scalability. While I'm aware of the standard performance issues (minimize calls to the database, reduce postbacks, cache, use client validation, DataReader vs. DataSet, etc...), I've really been impressed with the book so far. It's about a 1000 pages, and is very thorough yet practical.

I admit that I was surprised at the resourcefulness of some of their suggestions, such as how to improve ASP.Net performance by trimming page size:

  • Remove unnecessary white space between tags
  • Avoid long control names (it gets rendered into HTML)
  • Save JavaScript to separate physical files not just for code reuse, but also so that the client can cache it.

They also suggest several tools to help monitor performance:

Monday, May 9, 2005

Using the CLR Profiler

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/using_the_clr_profiler.htm]

In software engineering, our knowledge is limited to what we can test via cause and effect. If we cannot measure the effect of something, it's hard to really know about it. This is one reason why people know relatively less about security and performance than coding "standard" features - it's hard to reliably measure them. However, help is on the way. There exists a free tool, the CLR Profiler, that lets you measure resources in managed code. Resource consumption is linked to performance, so this gives you a tangible way to diagnose some performance-related problems in your .Net App.

Version 2.0 has a great 100 page tutorial. There are other links out there too, such as:

I find this useful to see measurable differences in code snippets. The tutorial shows the difference for using StringBuilder to concatenate strings, but that's just the beginning. For example, the code snippet below opens a file 100 times. If I don't close the reader, I can see the affect of this in the CLR Profiler's "Histogram by Age for Live Objects" chart. In my case, normally the number of objects (less than 34kB) living less than .5 sec was 34KB. If I don't close the reader, it's 800KB.

public static void In_WithClose(string strFileInput)
{
    System.IO.StreamReader sr = null;
    for (int i = 0; i < 100; i++)
    {
        sr = new StreamReader(strFileInput);
        sr.ReadLine();
        if (sr != null)
            sr.Close();
    }
} //end of method

This is a great tool that can be useful for diagnosing memory (and therefore performance) bottlenecks.

Saturday, May 7, 2005

Unit Testing Void Methods

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/unit_testing_void_methods.htm]

I was recently asked the good question "Should you create tests for void methods?". My answer: It depends. Let's look at the following example:

public class Foo1
{
    public Foo1()
    {
        _intCounter = 0;
    }

    private int _intCounter;
    public int Counter
    {
        get
        {
            return _intCounter;
        }
    }

    public void Increment()
    {
        _intCounter++;
    }

}

In this case, the void method Increment() changes the state of the Foo1 object, which can be measured by the Counter property. So, the following would be a decent test:

[Test] public void TestVoidMethod()
{
    Foo1 f = new Foo1();
    Assert.AreEqual(0,f.Counter);
    f.Increment();
    Assert.AreEqual(1,f.Counter);
}

The intent is that we want to always test deterministic logic, such as code that contains conditions, loops, or operators. While this is straight-forward with static functions (plug in x, get y), it can still apply to void methods. The difference is that a void method may be updating another property of an instantiated object instead of a return value.

However note that void methods may lack any logic to test. For example, the method below simply wraps some architecture block that writes out files. There's no logic here to test.

public void WriteFile(string strContent)
{
    ArchitectureBlock.WriteToFile(strContent);
}

Thursday, May 5, 2005

Securing Images From Unauthorized Users

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/securing_images_from_unauthorized_users.htm]

Sometimes we want to secure images so that only authorized users can view them. Private images might include proprietary diagrams or images with personal information (perhaps paychecks). The problem is that the nature of images in Html is simply a URL to an already-accessible file. For example, the source code for the Google logo at www.google.com is essentially . The src attribute is a relative path from the google main page, so you can directly view this image at http://www.google.com/intl/en/images/logo.gif.

For a secure image, we want:

  1. The application can access it
  2. The user cannot.

This can't merely be solved by trying to "hide" the images in some directory, because the page's source is public. They can't hide. However, we can use .Net to solve this by:

  1. Store our images in a file only accessible to the application
  2. Use System.Drawing to dynamically create an image from a file
  3. Response out that image to an ImgPage.aspx page
  4. Make an image in our main page, and set its source property to the ImgPage.aspx page.

This technique of dynamically displaying images in a WebForm is based off of MVP Scott Mitchell's article Create Snazzy Web Charts and Graphics On the Fly with the .NET Framework. The conceptual difference is that instead of dynamically creating an image (such as a chart) and outputting it, we're dynamically creating the image simply by loading in an image file.

The first step is easy. The second step requires some coding. The function below resides in ImgPage.aspx.cs. It assumes that you pass in the image file path in any way you see fit. One way is to get the filename from the querystring. For simplicity this method assumes just "gif" images, but you could get the image extension and set the type as appropriate.

private void Page_Load(object sender, System.EventArgs e)
 {
     string strFile = Request.QueryString["img"].ToString();
     SetImage(strFile);
 }
 
 private void SetImage(string strFile)
 {
     //Set Response type for an image
     Response.ContentType = @"image/gif";
 
     System.Drawing.Bitmap bm = null;
     using (bm)
     {
         bm = (Bitmap)Bitmap.FromFile(strFile);
         bm.Save(Response.OutputStream,ImageFormat.Gif);
     }
 }

First we set the page Response's content type. We then create a BitMap from a file, and save it to the Response OutputStream. Note that ImgPage.aspx is an empty page designed solely to receive this output.

Our main page has an image with the source property set to aspx page and its querystring, such as ImgPage.aspx?img=FilePath.gif. The main page code behind can then do whatever it needs to determine the correct querystring.

<asp:Image id="Image1" runat="server" ImageUrl="ImgPage.aspx">asp:Image>

While I've built a proto-type for this, I admit that I haven't tested it in an enterprise application, but it seems pretty promising.