Developer Blog
Articles about Using Microsoft Developer Tools

Getting Bit by Caching

Wednesday, December 31, 2008 1:48 PM by jonwood

I must confess, I’ve been bit by ASP.NET caching a couple of times now. It’s not that there’s anything wrong with ASP.NET caching—there isn’t. In fact, it’s not that ASP.NET caching is not important and cool—it is! But what seems like an easy-to-use feature can actually get fairly complex and can easily be misused on a dynamic Website.

Caching refers to saving a copy of a requested page on the server and, the next time that pages is requested, serving that copy rather than recreating that page. The performance improvements can be significant on a busy site, particularly if pages require a lot of code and database queries.

ASP.NET provides the OutputCache directive for caching a page. You provide a duration, in seconds, of how long until the cache should be discarded. Once the cache is discarded, any new request for that page will cause the page to be recreated.

<%@ OutputCache Duration="60" VaryByParam="none" %>

ASP.NET OutputCache directive

There are a lot of options to this directive. For starters, it can appear on pages other than a ASPX pages. You can also add it to master pages, web controls, etc. You can also have the cache unique to a particular query argument or a whole host of other conditions. For example, if a query argument specifies an ID of the item to be displayed, you wouldn’t want to use the same cache for all items. Otherwise, you’d enter a particular ID but would then see whatever item happened to be in the cache.

I won’t go into great detail about all the options available with the OutputCache directive. Perhaps I will attempt that in another article. Here, I simply want to make you aware that caching can cause some significant problems if you don’t carefully think things through each place you use it.

I downloaded the Personal Website Starter Kit from http://www.asp.net, a supposedly official Microsoft site. It’s a cool ASP.NET example (aside from a couple of significant problems). But I was still fairly new to ASP.NET programming and I spent an enormous amount of time trying to figure out why the picture browser page didn’t work reliably. For the most part it worked. But sometimes it would not advance to the selected picture. I studied and studied the code, and couldn’t figure out what was happening.

Finally, I started thinking about caching and, sure enough, someone had added a caching directive at the top of each page and the result was that the page sometimes appeared as it did the last time it was viewed rather than being updated with a new picture.

I don’t mean to scare anyone from using caching. I recommend you use it! But if a widely-used, example Website that is presumably from Microsoft uses caching incorrectly, then I think it’s safe to say that it’s not always immediately obvious what the ramifications of caching will be. On a dynamic Website, content changes. You need to ensure that the user always gets current content, and prevent caching of pages or objects that need to change. And, possibly, if you get bit by caching, maybe you’ll think of this article and not waste as much debugging time as I did.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   ASP.NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Dynamically Setting the Theme

Friday, December 19, 2008 4:06 PM by jonwood

Themes can be used to customize the look of your Website. If you need to select the theme based on user settings, you’ll be glad to know that ASP.NET allows you to set the theme of a page dynamically when the page is being created. This process is pretty straight forward; however, there are a couple of issues that may arise.

First of all, ASP.NET establishes the current theme prior to the page’s Load() event. In order to dynamically change the theme before the Load() event, you'll need to set it during the page’s PreInit() event.

protected void Page_PreInit(object sender, EventArgs e)
{
  Theme = "MyTheme";
}

Setting the Theme in the PreInit() Event

That was easy enough. But what happens if your site uses a master page? Master pages allow you to control the appearance of all the pages on your site from a single master page. So it makes sense to want to set the theme from the master page. However, master pages do not provide a PreInit() event. So setting the theme dynamically from a master page is not as easy as you might guess.

One way to deal with this is to create a class that derives from IHttpModule. This class can be made to respond to all page requests on your site, and it gets called just before the request is handled, in plenty of time to set the theme for the current page.

public class ThemeManager : IHttpModule
{
  public ThemeManager()
  {
  }
  public void Init(HttpApplication app)
  {
    // Set our handler to be called just before handling a request
    app.PreRequestHandlerExecute +=
      new EventHandler(Context_PreRequestHandlerExecute);
  }
  void Context_PreRequestHandlerExecute(object sender, EventArgs e)
  {
    // Note: If handler does not implement IRequiresSessionState or
    // IReadOnlySessionState then Session state will be unavailable
    if (HttpContext.Current.CurrentHandler is Page)
    {
      // Set theme
      Page page = (Page)HttpContext.Current.CurrentHandler;
      page.Theme = "MyTheme";
    }
    public void Dispose()
    {
    }
  }
}

Setting the Theme from an IHttpModule-Derived Class

In order to use this class, you’ll have to modify your web.config file.

<configuration>
  <system.web>
    <httpModules>
      <add name="ThemeManager" type="MyNamespace.ThemeManager" />
    </httpModules>
  </system.web>
</configuration>

Web.config Changes

Also, be sure to clear any theme settings from your web.config file. Otherwise, it’s possible for ASP.NET to get confused and possibly reference multiple CSS files.

This is the solution I used for a Website I was developing and it works just fine. However, it does require a bit of work. I then started thinking of a much simpler approach that would meet my particular requirements.

ASP.NET themes are quite powerful, and can be used to manage the appearance of various controls and images. Another thing themes do is let you specify CSS, or style sheets. But, for my particular needs, I wasn't using skins. The only thing I used themes for was for style sheets. If this is all your themes are used for, then a much simpler approach can be taken.

All you need to do is add a Literal control inside of the <head> section of your master page. Then, you can set it to include your style sheet during the master page's Load event.

Since you aren't modifying the look of controls using skins, there is no need to change this setting in the PreInit() handler. In fact, you could handle it even later than the Load event since all that needs to happen is your page references the correct CSS file. The final text needs to look something like this (don’t forget to escape the double quotes so they come out right from your scripting language):

<link href="Style.css" type="text/css" rel="stylesheet" />

Stylesheet (CSS) Reference

The user's browser will do the rest once the page has been created and sent to the user.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   ASP.NET
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed

SQLite

Saturday, December 13, 2008 9:09 AM by jonwood

MFC programmers wanting to store data to disk have a couple of choices.

Although there are a variety of third-party options available, the choice generally comes down to a home-grown solution that includes code to access raw disk files, or using a major database server.

Home grown solutions can be anything from fprintf() to complex data-handling systems. By coding it yourself, you can add just the code you need and have it work exactly how you want. Of course, it can also be a lot of work, especially if you need something more sophisticated.

Major database servers make it easier to efficiently handle large amounts of data. And, using SQL (structured query language), you have a lot of flexibility in how your application can extract that data. However, this can complicate distribution and installation of your application if it requires access to a bunch of additional modules or perhaps even a database connection.

I was recently writing an application for a client and our needs seemed to fall somewhere between these two choices. We didn’t want the coding and distribution overhead associated with a complete database server, but we did want some flexibility on extracting the data in order to be able to produce a number of reports.

For this project, we decided to go with SQLite. SQLite is a complete SQL database engine but works quite different than those you may be familiar with. For starters, SQLite is completely free of charge. And, although this means no support, there are some forums you can access and I’ve found support there to be pretty good.

Second, the library comes as raw source code. Although you could compile it into a DLL and call the DLL, we simply included the source code in our project. They provide a combined source code so all we had to do was include the one file and a header file and we were good to go.

Of course, SQLite does not run as a separate process as a database server would. It is simply a library of subroutines in our application (which we developed a class library around). But we didn’t need a database server. And because the database is now part of our application, we don’t need to worry about distribution issues, installation problems, version incompatibilities, or anything else of that nature. And we have full SQL support when querying our data.

SQLite has a few oddities. The main one is that it does not enforce referential integrity. If you delete a row that is referenced by a foreign key in another table, you now have an invalid reference. It is possible to use triggers to catch this and perform, for example, a cascading delete. For our purposes, this hasn’t really been an issue.

Another thing is the way it stores data. You can specify a column to be an integer data type, but it doesn’t mean that’s how it will be stored. You can easily assign a string to a field in that column. It will correctly sort those strings based on their integer values. You just don’t know how the actual data will be stored. This has never been an issue for us either.

All in all, I think SQLite is totally cool. I now have all the power of SQL in a stand-alone application. And, being free, the price cannot be beat. You’d be surprised how many applications are using it as well. From desktop applications to cell phones, it contains thoroughly tested code. Depending on your needs, perhaps SQLite is appropriate for your next project too.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   C++/MFC
Actions:   E-mail | del.icio.us | Permalink | Comments (4) | Comment RSSRSS comment feed

Editing Ribbon Bar Images

Saturday, December 13, 2008 8:37 AM by jonwood

If you’ve installed the Visual C++ 2008 Feature Pack or upgraded to Visual Studio 2008 Service Pack 1, you may already be working with the new ribbon bar control.

This control provides many new user-interface elements and cool new images. However, if you are like many people, you may have wondered how you can change those images. Even with all its powerful resource editing features, the current version of Visual Studio does not support editing the type of images used by the ribbon bar. You can open them in Visual Studio, but they will appear with strange black areas and will not be editable.

Ribbon Bar Images

So what’s different about the images used in the ribbon bar compared to those images used in icons, cursors, and regular bitmaps? Two things: The color depth and the alpha channel. Ribbon bar images use 32 bits per pixel to specify color values. This allows for images with a much greater color depth.

The alpha channel is a value that specifies the transparency of a pixel. Color values have historically used a byte each to specify red, green, and blue color values. In a 32-bit integer, this leaves a fourth byte available for the alpha channel. This means that we can specify the transparency of a given pixel with the same resolution we specify any of the other color components.

The alpha channel is great for smoothing the edges of images. Sometimes, bitmap edges can look jagged when dark outlines have awkward correlation with the underlying pixels. These edges can be smoothed somewhat by adding gray pixels to smooth the transition from black image pixels to white background pixels. But what happens if the background is black? The alpha channel allows you to fade the edge of an image into any background color. The result is much smoother outlines and transparent areas regardless of the background.

IconWorkshop

So if you can’t use Visual Studio, you’ll need another tool. Fortunately, Axialis has made arrangements with Microsoft to provide a free version of their IconWorkshop. This is a great little program. In fact, I registered the full version quite some time ago.

IconWorkshop has a recently added feature that displays an image strip bitmap as a collection of separate images, similar to how the toolbar editor does in Visual Studio. This makes it very easy to work with image strips for ribbon bars. I should point out that most of the ribbon images I put together these days are either some of those provided with Visual Studio, created using high-end graphics programs, or even imported from photos. IconWorkshop is great for importing various image types into a single image strip, even if you don’t use it to actually create the original images.

Application Button

There are two primary types of ribbon images that you’ll want to change. The first is the application or “jewel”. This is the image that appears in the round button near the upper left corner of the main window. By default, CMainFrame::InitializeRibbon() initializes this button to use the bitmap resource with the ID IDB_MAIN.

// Init main button:
m_MainButton.SetImage(IDB_MAIN);
m_MainButton.SetText(_T("\nf"));
m_MainButton.SetToolTipText(strTemp);

Default initialization of ribbon application button

Note that when you load main.bmp (IDB_MAIN) in IconWorkshop, it will appear as an image strip with a single image. Don’t let that throw you. Just edit the image and save it and you’ll have a new application button image.

Command Images

The other primary type of images are for the actual ribbon commands. As described before, these images are stored as image strips where a single bitmap contains a number of different images. The image strip is set when a ribbon bar category, or tab, is created. Two image strips are specified: one for large images and one for small images. For example, the default code specifies the image strip bitmaps with the IDs IDB_WRITESMALL and IDB_WRITELARGE when creating the Home category. If you open either of these bitmaps, you can see the images they contain.

// Add "Home" category with "Clipboard" panel:
bNameValid = strTemp.LoadString(IDS_RIBBON_HOME);
ASSERT(bNameValid);
CMFCRibbonCategory* pCategoryHome = m_wndRibbonBar.AddCategory(strTemp,
  IDB_WRITESMALL, IDB_WRITELARGE);

Default initialization of category image strip

When a ribbon element such as CMFCRibbonButton is created, you specify the zero-based index for the image to be used with zero specifying the left-most image. You can specify two indexes, one for the index into the small image strip, and one for the index into the large image strip. If you only specify the index for the small image, then that element will only use the small image.

Conclusion

So there are a few new things to learn here and a few more tool that you’ll need.

Although the ribbon bar can seem a bit awkward to experienced users accustomed to using toolbars and pull-down menus, we’re told that research shows the ribbon bar layout to be much easier for most users to learn.

When done well, ribbon bars can look great and support some really cool images. This is definitely something to get on top of if you are designing modern interfaces in MFC.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   ,
Categories:   C++/MFC
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed