Thursday, January 31, 2008

Installing Subtext on Vista - Request is not available in this context

Just a quick note when you are installing Subtext on Vista. After you add a webiste in IIS7, set your connection string, then browse to your site, you may get this error:

System.Web.HttpException: Request is not available in this context

To fix it open IIS, right-click your site, select Advanced Settings, change the Application Pool to Classic .NET AppPool.

After scratching my head twice over this same problem, I decided to make a quick entry. I hope this helps someone else.

Friday, January 04, 2008

Convert List<A> to List<B> with a Lambda One-Liner or LINQ

C# 3.0 is really cool. There are some great new language features, including lambdas. Lambdas are basically an easy way to write anonymous functions.

Suppose you have two types: Tree and Pine. Pine inherits from Tree. Now suppose you have a List<Tree>, but you know that every object in the list is of type Pine. It would be nice to convert this list to a List<Pine>. There are several ways to do this. A foreach loop might be the first to come to mind. This would take a few lines of code. Suppose trees is a List<Tree> and pines is a List<Pine>.
  foreach (Tree tree in trees)
  {
    pines.Add((Pine)tree);
  }
Another way to convert the list is to use the ConvertAll<T> method of List<T>. It calls for a delegate as an argument. This would be a bit burdensome if there wasn't an easy way to write an inline delegate, but with C# 3.0 there is! This is what a lambda can do. Check it out:
  pines = trees.ConvertAll<Pine>(t => (Pine)t);
That converts a List<Tree> to a List<Pine>. Is that not sweet? What this lambda is doing is returning an anonymous function that takes t as a parameter and returns (Pine)t. The compiler figures out that t is of type Tree. ConvertAll then uses this function to convert each element of the list.

Now suppose your list of trees had some Tree objects and some Pine objects. The above example would fail on the Tree objects since they cannot be cast to Pine objects. In the foreach loop, it would be easy to skip over the ones that wouldn't cast:
  foreach (Tree tree in trees)
  {
    if (tree is Pine)
    {
      pines.Add((Pine)tree);
    }
  }
With the lambda, it isn't as straight-forward, but you can do it by using the FindAll method:
  pines = trees.FindAll(t => (t is Pine)).ConvertAll<Pine>(t => (Pine)t);
The problem with this is that the loop is iterated twice.

A nicer way is to use the new LINQ capabilities:
  pines = (from t in trees where t is Pine select (Pine)t).ToList<Pine>();
Now, we don't even see a lambda in our code (but C# uses them behind the scenes with LINQ). In this statement, we are getting all the Tree objects from trees that are of type Pine. Then, before we get select them out, we cast them to the Pine type. The final thing to do is convert the IEnumerable to a List<Pine> using the ToList method.

As it turns out, LINQ is useful for more than just getting data from SQL Server. However, if you aren't too keen on the LINQ syntax, there are still a number of useful extension methods in the System.Linq namespace. Using OfType() and ToList(), we can rewrite the code as:
  pines = trees.OfType<Pine>().ToList<Pine>();
With this we are back to iterating the loop twice, but it is nice that just by adding a "using System.Linq" line to the top of our file, these new methods are tacked on to our List<Tree> (and all other lists for that matter). Again, extension methods are a new language feature. You can write your own extension methods too.

There are lots of other cool, new language features in C# 3.0, so go check them out!

Monday, November 26, 2007

Help Rid the World of IE6

You can help web developers make better websites for you to use. If they aren't wasting their time fixing their sites to work in IE6, they can spend it on making better sites. Do your part by installing IE7 or FireFox on your family's computers.

Internet Explorer 6 is old. IE7 was released over a year ago, but the usage share of IE6 is still at 48% according to thecounter.com. IE7 is even included in Window's Automatic Update, and it still isn't gaining enough ground.

But what's the problem? If someone wants to browse the web with a dilapidated browser why should we stop them? Well, because it affects everybody. In many places, you can't just drive any car you want to. Your car has to meet emissions standards. If it doesn't, it pollutes the air more than it should and makes breathing difficult for everyone. Laws were set up to make the air a little better for everyone's lungs. Likewise, if you are using an old browser you are putting off emissions. These emissions are additional work for web developers. IE6 has a number of CSS problems that don't exist in IE7, Firefox, or Safari. All browsers have some rendering problems, but IE6 has more and worse problems.

The good news is that IE7 is much better. The bad news is that not enough people are installing it. IE6 is at 48% usage share, while IE7 is at 32%. IE5 is finally obsolete with only 1% market share.

The simple easy thing you can do is to abolish IE6 in your own sphere of influence. When you go to your parent's house for Christmas this year, bring IE7 and FF on a flash drive with you (or download it there). Here are the links:

Installing IE7 should be your first choice since it completely obliterates IE6 (of course you could also install FireFox, but please make sure to get rid of IE6, that's our goal). However, you can only install IE7 on XP SP2 and Vista. If your mom's computer is running Windows 98 or some other old OS, the next best option is to install FireFox, make it the default browser, and delete the Internet Explorer shortcuts. Better yet, buy her a new computer.

Perhaps if we all work to wipe out IE6 this Christmas, we can enjoy a more standards friendly web next year. Merry Christmas!

Sunday, September 09, 2007

Testing ASP.NET 2.0 Apps In IE 6 On Vista

I have Visual Studio 2005 and 2008 Beta 2 installed on Vista Home Premium. I recently made a site that works fine in IE 7, Firefox, and Safari, but not in IE 6. It renders horribly. I can only guess that it's the broken box model, or something to do with floats. I need to test it, but how?

It isn't as simple as you might think. You can't install IE 6 and IE 7 side-by-side. You have to install Microsoft Virtual PC 2007, load an XP image with IE 6, and install the modified Cassini web server from ultiDev on Vista. Lets get to the details.

Download Stuff

First we need to download a lot of bits. Cassini and VPC 2007 are small, but the VPC image is pretty big. Dowload these files:

You'll have to wait a while for that first one, but after you get the files we'll move on to installing VPC.

Installing Virtual PC 2007 and Running the Image

Run the setup program, and take all the defaults. After it is installed, you'll have to run the IE6_VPC.EXE to extract the VPC Image. After it is extracted, you'll have a large .vhd file. This is the virtual hard drive that contains XP.

We have to create a new virtual machine, so run Virtual PC 2007. On the Console, click New. Choose "Create a Virtual Machine", name it, choose XP as the OS, and I reccomend bumping up the RAM to 512 MB if you can. Then, choose and existing hard disk, and navigate to the one you just extracted.

After you boot up the virtual machine, we'll enable the page file for better performance. Click Control Panel, System, Advanced, click Settings under Performance. Click Advanced, under Virtual Memory click Change. Select System Managed Size, click Set, then clik OK. Exit the System settings.

Now we have to turn off the proxy settings in IE. Open IE (it's IE 6!) and click Tools, Internet Options, Connections, LAN Settings. Uncheck "Use a Proxy Server for Your LAN".

So far, so good. You should be able to get to Google and other web sites now, but you'll have problems connecting to the built-in web server in Visual Studio. It's not designed to serve pages to other computers. That's why we need the Cassini Web Server. If you have Vista Ultimate or Business you could use IIS and skip installing the Cassini web server.

Installing and Configuring Cassini

Run the Cassini setup program, and choose all the defaults. After it is installed, run the Cassini Web Server Explorer. It will fire up a locally hosted web application. Click on Register to setup a new hosted application (the one you view on IE6). This screen can be somewhat annoying because it wipes out your file entry when you choose other options. Just navigate to the default.aspx file of your application after the other options are set.

First, either use a system assigned port or select a port. I chose port 80 so my ASP.NET app would be the default on the machine, but I don't think you have to. Click Generate to generate some settings, Set the Name, and navigate to the default.aspx page of your web app. I left the Description blank, but add one if you like. Click Save.

You should now be able to get to the web app from Vista. Your host OS, that is. Open a browser and type "localhost" in the address bar. If you didn't use port 80, and you used, say 65355 instead, type "localhost:65355" in the address bar. The site should open. If it didn't then something is wrong.

Connecting to Cassini from IE 6

In order for your Virtual PC to access Cassini on your host machine, you'll have to either disable the firewall in Vista, or create a rule to allow access. I just disabled it - both the Domain Profile, and the Private Profile to get it working.

Now you have to find out the IP address of your host OS, so open a command prompt and type "ipconfig". Your IP address should be listed after IPv4 address. Hopefully you are not using IPv6. It has some bugs (at least I had problems with it). Remember this address. Mine was 192.168.10.200.

Now back on the VPC. Open IE 6, and type the IP address of your host computer into the address bar. Again, if you specified a port other than 80, you'll have to type the IP address followed by a colon and the port. e.g. "192.168.10.200:65355". The site should open, and now you can debug it.

Conclusion

After some headaches, a lot of downloading, and configuration, you can now test on IE 6. For complete browser testing, I reccomending testing your site with IE 6, IE 7, the latest of Firefox, the latest of Opera, and the latest of Safari. Yes, a Safari 3 Beta is now available for Windows. Good luck. Maybe one day browser testing will be a little easier. We can only hope.

Update 10/12/2007

I found out that you can install IIS 7 on Vista Home Premium. It is limited, but it should work fine for development. If you install IIS, you won't have to install the Cassini web server. The one catch is that NT Authentication will not work out of the box, but there is a fix.

Wednesday, August 29, 2007

Creating SPF Records in GoDaddy for GAFYD

Sometimes by trying to simplify things companies make them harder. I wanted to create an SPF Record for my domain. I'm using Google Apps For Your Domain (GAFYD) to host the email, and Google's instructions are simply:
To set your domain's SPF record, publish the following TXT record on the DNS resource: v=spf1 include:aspmx.googlemail.com ~all
Well, with GoDaddy's "easy" management tool, you can't just specify that. They have a wizard for you to use. By trial and error, I finally got the right SPF record. Here's how:
  • Login, and go to the "Total DNS Control Panel"
  • Under the TXT section, click "Add SPF Record"
  • Select "An ISP or other mail provider" and click OK
  • Select the "Outsourced" tab, and enter aspmx.googlemail.com as the outsourced domain
  • Click OK
  • GoDaddy will display a confirmation with the correct SPF record listed.
  • Click OK
There you go. It would have been easier if there was no wizard and you could just cut and paste it. Hopefully, my email doesn't quit working...

Friday, November 10, 2006

Crystal Reports - Access is denied

Crystal Reports can be frustrating. Especially the Crystal Reports Engine. In an ASP.NET 2.0 page I'm trying to load a Crystal Report using the ReportDocument.Load() method, and I kept getting the error:

Access is denied.
System.Runtime.InteropServices.COMException: Access is denied.
The asp.net user already had permission to the .rpt file, but what I didn't know was that Crystal Reports creates its own temp file during the Load() method. This file is put in the directory specified by the environment variable "TMP". You can view the contents of this variable in code by using this method:

System.Environment.GetEnvironmentVariable("TMP")
Giving the ASP.NET user Full Control to this directory will work, but what I really wanted was for Crystal Reports to use a directory that I specified in the web.config file. To do this I set the environment variable, loaded the ReportDocument, and changed the environment variable back.

...

'Get the Crystal Reports Temp directory from web.config
Dim TempRoot As String = ConfigurationManager.AppSettings("CRTempDir")

Dim oldTmp As String = System.Environment.GetEnvironmentVariable("TMP")
System.Environment.SetEnvironmentVariable("TMP", TempRoot)

Dim rpt as New ReportDocument()
rpt.Load("myReport.rpt")

System.Environment.SetEnvironmentVariable("TMP", oldTmp)

...

'Be sure to call this as it will delete your temporary .rpt file
rpt.Dispose()
When you run your web page, Crystal Reports will create a temporary .rpt file using the name of your .rpt and adding a Guid to the end of it. Crystal Reports also writes a .tmp file for some reason. Once Dispose() is called on the ReportDocument both of these temp files will be deleted.

Wednesday, January 25, 2006

Seperate Processes Sometimes Break ASP.NET Session

I ran across an interesting problem this morning. A user was browsing the Property Information System, and when he clicked on the map to identify a property the popup window would launch but it would display an ASP.NET Error Message, "Object reference not set to an instance of an object." I examed the source, and on page load the popup gets stuff from the ASP.NET session.

It was behaving like his session had timed out, even though it shouldn't have for 20 minutes.

After some time on the phone we managed to track it down to a setting in Windows Explorer (not Internet Explorer). In Tools|Folder Options on the View tab, there is a setting called "Launch folder windows in a seperate process." As it turns out, if you have this set, and type the URL into the address bar of Windows Explorer, popups launch in a seperate process. This was creating a new session on the server. So any session information from the parent window was not available to the popup window.

The solution: Don't use Windows Explorer that way (launch I.E. for browsing) or don't rely on the session like we used to say back in the days of ASP 3.0.

My CSS References

I was going to just email this to a couple of co-workers, but I decided it would make a decent little blog post. These are the some of the CSS sites that I read and could help you out with learning and working with CSS.

Good Sites:
CSS Vault (lots of good examples)

Blue Robot (free templates)

Glish (free templates, good examples)

CSS Zen Garden (a classic, 1 HTML page styled by your choice of CSS)

Position is Everything (they talk a lot about hacks, in fact Holly Bergevin is the creator of the "Holly Hack")

References:
A Bunch of CSS Links (a bunch of links, important ones highlighted)

MSDN (I use this for reference a lot)

Interesting Articles:
A CSS Framework (About making a reusable CSS to build upon)

The 10 Best Resources for CSS (a good article with more links, some of which are here)

One clean HTML markup, many layouts (this is cool because he doesn't use any hacks)

Image Map for Detailed Information (a neat little example)

Blogs and the like
Dustin Diaz (a good writer, he talks about design, CSS, and Javascript)

A List Apart (good articles, multiple contributers)

Content with Style (another great one with multiple contributers)

Mezzoblue (beautiful colors and some good articles)

Jason Santa Maria (he mostly talks about page design, but I really like his post on Grey Box Methodology)

Jason Graphix (he mostly talks about page design too)

Clagnut (a nice looking site built with CSS, and some articles)