When is a cache not really a cache

I spent a large portion of the day inside of the Caching Application Block.  Specifically, a colleague and I were tracking down what appeared to be a nasty threading bug caused by having the creation of two different cached objects that were related to one another.  As it turned out, the bug that existed couldn't explain away all of the behaviors that we observed.

As it turns out, there was what appears to be a poorly documented aspect of the Caching Application Block that was causing us grief.  The problem is that the default number of objects that the cache can store before scavenging begins is set very low.  Specifically, it is set to 5.  As well, there is a UtilizationForScavenging setting (by default, it is 80) that lowers this number ever more.  Once the cache contains the (maximum * utilization / 100) items, the scavenger starts to remove the excess items from the cache, trying to keep the number of items below the calculated value.  With the default values, this means that no more than 3 elements will be saved in the cache at a time.  The scavenging class uses a least recently used algorithm, however if you're using an absolute time expiration, there is no 'last used' information saved.  So the scavenger appears to remove the last added item. 

That's right.  Unless you make some changes to the default config, only three elements are kept in the cache.  Probably not the performance enhancer that you were looking for from a cache.  Fortunately, the values can easily be changed.  The can be found in the ScavengingInfo tag in app.config. And there is no reason not to set the maximum value much higher, as there is no allocations performed until actual items are cached. It was just the initial surprise (and subsequent fallout) that caused me to, once again, question how closely related the parents of the designers were.  But only for a moment. ;)

As one further word of warning, if there is no ScavengingInfo tag in the config class, then the default class (the same LruScavenging class just described) is used. And instead of getting the maximum cache information from the config file, a file called CacheManagerText.resx is used.  In that file, the entries called RES_MaxCacheStorageSize and RES_CacheUtilizationToScavenge are used to determine how many items to keep in the cache.  Out of the box, these values are set to the same 5 and 80 that the config file contains.

Solving the "No such interface is supported" problem

I was asked a question today about a fairly common error that occurs when serviced components are used in conjunction with ASP.NET. Specifically, a COM+ component (one that is derived from ServicedComponent) was being used on an ASP.NET page.  When the page was loaded, an error of "No such interface is supported" was raised.

To understand the why of this error requires a little bit on knowledge about COM+.  When a serviced component is first instantiated, the CLR checks the COM+ catalog for information about the runtime requirements of the class. But if the class had not previously been registered, then no information will be available.  To correct this discrepancy, the CLR automatically creates a type library for the class and uses that information to populate the COM+ catalog. This mechanism is called lazy registration. 

But wait.  It requires a privileged account in order to register a component in the COM+ catalog.  In particular, you need to be a machine admin.  And, unless you have been silly enough to grant the ASP.NET user admin rights to your machine, the update of the COM+ catalog fails.  No catalog information, no instantiation.  An unsuccessful instantiation means an exception.  An exception that includes an error message of "No such interface is supported". Go figure.

So ultimately, the solution is not to depend upon lazy registration of COM+ components that are deployed for use in ASP.NET.  Instead, perform the registration using the regsvcs.exe command manually.

Halo2 is coming, eh?

For those of you who are Halo fans, check out the following link (http://www.techstuff.ca/archives/915.html) describing what is different between the American and Canadian versions of Halo 2.  Thanks to Scoble for the link.  And I'd be happy to answer questions from Americans explaining why it's funny.  I'm familiar with discussing stuff like this with my American wife. ;)

SqlConnection woes on the Compact Framework over WiFi

Last night at the Toronto .NET Users Group talk I did on mobility, a gentleman had a question about directly connecting to an Enterprise SqlServer database from a Pocket PC using the Compact Framework. His users run on a shop floor and some times they lose their wifi signal. While he doesn't keep the SqlConnection open the whole time, it seems that when a wifi signal is back alive his application can't connect to the database using a SqlConnection.Open anymore - despite that he can still ping the server.

He was correctly doing a SqlConnection.Close in a finally clause around his data access, but I suspect that even though pooling is not supported on the compact framework, this is not doing a proper disconnect of the physical connection (a Sql Profiler session would probably tell you that for sure). So a using block in C# will ensure that the SqlConnection is disposed of immediately and will properly terminate the connection. So if between calls you lose and reaquire your wifi connection you'll be starting a bran new connection the next time. It's still a good idea to put all of your actual work in a try/catch/finally block with a SqlConnection Close in the finally.

using (SqlConnection cn = newSqlConnection(CONNECTION_STRING ))
{
 try
  {
   cn.Open();
   //do some work with the connection
  }
  catch (SqlException ex)
  {
   //error handling
  }
  finally 
  {
   cn.Close();
  }
}

Cookieless Sessions and Security

In a previous blog, I pointed out that Microsoft had created an HttpModule that mitigated the ASP.NET cannonicalization issue that was first described a couple of weeks ago. In one of the comments, Amir asked about the security issues surrounding the use of cookieless sessions.  Specifically, he was wondering if ASP.NET could tell if a request containing a cookieless session component was coming from a different browser instance or even a different location.  In brief, the answer is “No“.

When used as part of a plain text web site (i.e. no SSL), cookieless sessions are not secure at all. The session id is placed into the URL in every local link on a page.  The form of the URLs would not be as follows:  http://domain.com/(sessionid)/Page.aspx. This session id is not automatically tied to a specific browser instance or even the IP address of the initial request.  There is no way that I'm aware of to tie the request to a browser (other then using cookies ;). And while a session can be associated to an IP address, this requires some additional work on your part, in the form of an HTTP Module.  The association between session Id and IP address could be done by generating a hash of the IP address for the request (Request.ServerVariables ["REMOTE_ADDR"]) and the session id and using the resulting value to access the session variables.  However, this solution doesn't take into consideration the case where people are behind a proxy that causes the IP address to change from request to request. For this, you might want to just use the first two components of the IP address, since these are not normally varied by the proxy. But if the spoofer is on the same subnet...  As you can see, all in all, this is a difficult problem to solve.

I should probably mention that cookie-based session suffer from the same problem.  There is nothing inherent in how cookied sessions work that makes them safer than their cookieless counterparts.  A hacker can easily create a request that includes a spoofed cookies containing a hijacked session identifier.  But at least a cookie-based session solution can use SSL to encrypt the entire request.  Since the session is not included in the URL directly, it is not easily accessible if the request/response gets hijacked.

So to summarize, while cookieless sessions are nice in theory, in practice they really should only be used on sites where every page is accessed through SSL.  And the implementation should be customized to ensure that a portion of the IP address is used to verify the originating IP address of subsequent requests corresponds to the original request.

Remove Those Annoying System Tray Balloons

If you're like me, the system balloons that are automatically popped by system tray application are annoying.  This blog from Scott Howlett describes how to eliminate them from your life.

Continuous Builds and Lava Lamps, Part 2

A couple of months ago, the idea of using a pair of lava lamps to signify the current status of the continuous made the rounds.  In fact, a blog on Pragmatic Automation description how Curtis Olson got it running.  A client of ObjectSharp's has taken it a step further.  Because the development team is located both in Canada and in Europe, they not only set up the lava lamps here.  They also hooked up a web cam pointing at the lamps so that the European developers could be kept informed of the build status. Technology at it's finest.

Get lost, have fun.

Ok this is too cool. Bell Mobility has this Location Service called MyFinder. Using Cellular triangulation they can figure out pretty close to where you are. It costs 25cents to locate yourself on any Bell Mobility Cell phone with a browser (plus air time ). You can do things like find the nearest gas station to where you are right now (or ATM, restaurant, etc.) and then using Map Point will give you driving/walking directions. I tried out this service in Waterloo and it found me within a block of where I actually was. Bell says within 150m. In my example that would be pretty close. So your mileage might vary (no pun intended).

If you are lucky enough to have Sanyo 8100 or an Audiovox 8450/8455 you can also use MapMe service which will download a map to your device and your location plotted on it - along with nearby places. This appears from the screenshot to be something along the lines of a Pocket Streets derivative. It costs $5 (one time) for the software, and again 25 cents to be located per use plus air time (unless you have the Mobile Browser Bundle).

Bell Mobility also has a few multiplayer games that you play against people nearby. Less cool. Get a life.

Perhaps the most (potentially) practical is a #TAXI phone number that connects you with the first available taxi based on your location. It uses many cab companies. It sounds like they might find you a taxi parked around the corner but I don't think it quite works that way. It found my city and routed me to the phone number of the nearest taxi company. It also sent me a text message with their direct phone number. A $1.25 a call? The taxi company should pay for that - no?

www.bell.ca/finderservices

You can develop applications using this service too. If you are lucky to live in Canada and be a Bell Mobility Subscriber - then you are in luck (as I am) since Bell is now providing realtime MS MapPoint Location Service. It almost makes up for being on a CDMA network and having that limited phone selection problem.

Microsoft MapPoint Location Server is a new component of Microsoft MapPoint Web Service. You will install this component (along with SQL Server) in your enterprise and using the MapPoint Web Service and location data from your provider you can get an inventory of all the people in your company and their locations. For doing dispatch type of applications, 150 meters is probably close enough. General Information on both here (http://www.microsoft.com/mappoint)

MSDN Universal, Enterprise, and Professional subscribers are eligible for a free subscription to MapPoint Web Service (a requirement of using MLS)(https://s.microsoft.com/mappoint/msdn/msdnspec.aspx)

Bell Mobility Developers Web site for location based services (http://developer.bellmobility.ca/lbs/)

 

 

Automatic mitigation for ASP.NET vulnerability

By now, most of you will have heard about the ASP.NET vulnerability that allows creatively formed URLs to bypass forms or Windows-based authentication.  And while there has been a piece of code that can be added to global.asax, Microsoft has released a more easily deployed mechanism for mitigating the security risk.  Check out http://www.microsoft.com/security/incident/aspnet.mspx to download an msi file that installs an HTTP Module that protects all of the sites on a  web server.

Looking for a few good developers

Barry has already mentioned it here, but on the off chance that there are people who read my blog that aren't subscribed to his, let me reiterate.  Things are quite busy here at ObjectSharp.  While it's not necessarily accurate as a measure of the economic health of the world, in our little microcosm, business has been quite healthy.  And the new year is looking good as well.  There are some projects coming down the pipe that look interesting.  And by interesting, I mean using technologies like BizTalk Server and Whidbey.  So if you're interested in joining an incredible team and are in (or are willing to move to) Toronto or Vancouver, then send your particulars to careers@objectsharp.com