If you need to create a composite key (for a dictionary for example) where the natural key could come from multiple sources a standard technique is to prepend the source to the natural key to ensure that it is unique. However, this can still cause duplicate keys so to solve this problem you should always add a delimiter between any concatenations that you do.
The problem is easily illustrated by looking at how files are managed in folders. Typically the composite key is the fully directory path and file name which identifies the file you are looking for. The delimiter is the backslash.
Say you had 2 files: bat.txt and mybat.txt
Let's say that they were in 2 directories:
c:\temp\somy and c:\temp\so
i.e.
c:\temp\somy\bat.txt
and
c:\temp\so\mybat.txt
Without those backslashes we would have:
c:tempsomybat.txt
and
c:tempsomybat.txt
giving us the same key.
So in code you may have:public void AddItem(string source, string itemName,
object data, Dictionary<string, object> myDictionary)
{
string compositeKey = source + "+" + itemName;
myDictionary.Add(compositeKey, data);
}
Sunday, July 31, 2011
Creating a composite key in your container
Tuesday, July 26, 2011
Disable thumbs.db in Win7
Notes for self on how to do this.
- Start Local Group Policy Editor.
- From start menu type gpedit.msc and hit enter.
- Navigate the left pane:
- User Configuration
- Administrative Templates
- Windows Components
- Windows Explorer
- On right hand side find:
- Turn off the caching of thumbnails in hidden thumbs.dg files
- Double click this item.
- Change value to Enabled
Other notes:
Might need to log off and log on again.
Will not delete existing thumbs.db file.
Sunday, June 5, 2011
Time taken for Google to de-index 301 redirect pages
inurl:/old/folder/pattern site:mysite.com
I entered the number of URL's into a spreadsheet for each of 3 folder patterns. Each pattern started off with 13, 18, and 87 URL's in Google's index. The objective of the exercise was to see how long it would take Google to de-index these pages. Here is a chart of the results:
The folder pattern with 87 URL's is shown against the right axis and the other two against the left.
Expectations:
My expectation was that as soon as Google found the new URL's (it found almost all of them within 5 days) that it would rapidly de-index the old URL's. Remember that I'm telling Google that this is a permanent (301) not temporary (302) redirect.
Actual results:
- It took around 55 days to naturally de-index all the pages. Much longer than I was expecting.
- The de-indexing for the 2 smaller collections of pages was linear.
- The de-indexing for the larger collection of folders was sudden and this happened after 48 days.
My surprise is how long it took to do that.
I'm not going to show a chart of the indexing of the new URL's because it's exactly as you would expect with the line rising rapidly up to the previous values. As I mentioned, 93% of the new links had been indexed within 5 days of them appear on the site and 100% had been indexed by day 13.
Tuesday, May 31, 2011
Loading a web page in a browser
Tony Gentilcore has just written a good post on How a web page loads and why blocking needs to take place when scripts and CSS load. I'm hoping that he's going to follow this up with a post on the SPDY protocol which looks pretty interesting for a faster web.
Google say that SPDY is an experiment with protocols for the web. Its goal is to reduce the latency of web pages.
At the time of writing this the third draft of the specification for SPDY could be found here.
One of the advantages that SPDY provides is that the resources needed by the page (JavaScript, images, CSS etc.) can be sent to the client in a compressed header and requested by the client before the client parses the HTML.
There's no indication if Google are going to push this specification yet because it's still experimental. One of the great advantages about owning an increasingly popular browser (Chrome) and a couple of popular web sites is that you can define the transport layer when your users are using your software end-to-end.
Tuesday, April 19, 2011
Optimizing CSS in ASP.NET MVC
The CSS files in a web application don't change very often. For this reason they are usually cached by the browser to improve performance. These are the steps that I take to optimize CSS files from my web apps. Although I'm using ASP.NET MVC this can be applied to any web app written in any language on any platform.
- Combine all CSS files into a single file.
- Replace tokens.
- Minify the combined CSS file.
- Cache the CSS file on the server.
- Name the CSS file with a timestamp.
- Compress the output to the browser.
- Set the browser cache date to a far future date.
1. Combine all CSS files
To make a project more manageable you might want to maintain multiple CSS files. I setup a pattern so that I can easily combine the files without changing the code. For example, precede each CSS file with a 2 digit number that dictates the order in which they should be combined:
01_main.css
02_forums.css
03_footers.css
The first time your CSS file is requested your code will read all the CSS files from the CSS folder and combine them in alphabetical order.
Complications: Sometimes you might want another css file added in there based on browser. For example, you might have another CSS file you only want combined with the "numbered" css files if the browser is IE6 or IE7. In cases such as that you would create several different combined files on the server and serve up the appropriate one at runtime.
At the end of this step you have an in-memory string representing the combined CSS files.
2. Replace tokens
This is an optional step but you might have image URLs in your CSS that reside on different subdomains depending on your environment. For example, in my dev and test environments the images are in a path off the dev and test domains. However, in production, the images are on one or more sub-domains in order to parallelize the image downloads in the browser.
If your configuration follows this pattern then you might want to put tokens in the CSS files which are replaced at runtime depending on the environment.
3. Minify the combined CSS file
Run the combined CSS file through a minifier to make it as small as possible. This file is only going to be read and used by a browser so pretty formatting and extra whitespace is no longer needed.
If you're developing on the .NET platform then you can use the YUI Compressor for .NET to minify your CSS. Once you've included the library in your project it will require a single line of code:
string minifiedCSS = CssCompressor.Compress(combinedCSS.ToString());
4. Cache the CSS file on the server
Once you've built and minified the CSS file (steps 1 and 2) you will probably want to cache this on the server so you don't have to do this again. How you cache it is up to you. ASP.NET has a cache object you can put it in or you can use a static variable, or singleton etc.
5. Name the CSS file with a timestamp
In the <head> section of your HTML you need to reference your CSS file. I do this by referencing a controller and action with a timestamped filename as the single parameter. For example, the served up HTML will look something like this:
<head>
...
<link href="/site/css/20110418095157.css" type="text/css" rel="stylesheet" />
...
</head>
In my .master file for the site or _Layout file for my razor views I have the following code:
<link href="<%:MySingleton.Instance.GetCssFileName() %>" type="text/css"
rel="stylesheet" />
TimeSpan duration = TimeSpan.FromSeconds(15552000);
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetExpires(DateTime.Now.Add(duration));
Response.Cache.SetMaxAge(duration);Wednesday, February 9, 2011
ASP.NET MVC3 Razor Notes - Partial Views
What's the difference between Html.RenderPartial() and Html.Partial()?
Html.RenderPartial() is an HTML helper method that was introduced in MVC1 and writes directly into the response object.
Html.Partial() is an HTML helper method that was introduced in MVC2 and like the other HTML helper methods returns a string and does not write into the response object.
Both helpers are used with partial views (sometimes still called controls) to implement the DRY principal of shared View code across multiple pages.
In the MVC WebForms View Engine views have the extension .aspx and partial views .ascx. This makes it easy to distinguish between views and partial views. In the MVC Razor View Engine both views and partial views have the extension of .cshtml. In order to easily distinguish between a view and a partial view in your project I suggest that you precede the partial views name with an underscore.
ASP.NET MVC3 Razor Notes - view data
The WebViewPage in an abstract class that inherits from the WebViewPage<TModel> generic abstract class.
Two properties of the WebViewPage<TModel> generic abstract class are:
- Model (dynamic)
- ViewData (key/value collection)
Among other properties, the WebViewPage adds:
- ViewBag (dynamic)
The ViewBag property is another way to get to the ViewData data.
For example:
If in the controller you did the following:
ViewData["website"] = "guyellisrocks.com";
ViewData["somenumbers"] = Enumerable.Range(0, 10);
Then in the view you could access that data through the ViewBag:
<div>
@ViewBag.website
</div>
@foreach (int i in ViewBag.somenumbers)
{
<div>
@i
</div>
}
and this would emit to the web page:
