matthew ephraim

Taming Visual Studio’s Web Server

May 14th, 2008

When I develop my sites locally using Visual Studio, I like to have the conditions on my local machine match the conditions on the actual web server as closely as possible. Part of doing that is making sure that my urls are formatted the same locally as they will be on the live site. Unfortunately, by default, Visual Studio’s built in web server makes the urls for a local project look a little bit different than they will when the site is actually deployed. This can be remedied quickly with a few changes to your project’s properties.

The Issue

When you first start a new project up in the debugger, Visual Studio will start the built in web server and open your default web browser with a url that looks something like this:

http://localhost:8080/Demo/Default.aspx

There are few problems with this url. First, the web server is not running on port 80, so the url contains the port number for the web server. This is an aesthetic problem, but it can also create issues if you plan on having your site behave different based on values that are found in the hostname. For example, if you have a site that has separate subdomains like “people.example.com” and “places.example.com”, and each of those subdomains shares the same codebase, it’s difficult to test that behavior locally if you don’t have your site running on port 80.

A second problem is that instead of having the root url immediately after the hostname, Visual Studio treats “/Demo” as the root of your site. This causes all kinds of problems if you want to use relative urls. It can also cause problems if you want use a url rewriter that relies on regular expressions to determine where a url goes.

Here’s how you can fix it.

Setting the Web Server Properties

To fix the port number and the site root problems, first open the Solution Explorer tab and select your project in the in the list of items.

Solution Explorer

Next, open the Properties tab and change the “Use dynamic ports” option from True to False. This should allow you to change the Port number to port 80. One issue that I’ve noticed with various versions of Visual Studio, both full and express, is that sometimes you need to close the Properties tab and reopen it before Visual Studio will allow you to change the port number. Finally, change “Virtual path” to “/” so that the root of your site will be immediately after the host name.

Properties

Now, when you start up the built in web server, you should be able to access your local site at “localhost”. No port number or project name after the url hostname necessary.

Creating some urls

At this point, the only url where you will be able to access your local site at is “localhost”. This is fine for simple sites, but I always lke to have a url like “matt.dev” where I can access any sites that I’m running on my localhost. That way, if I need to use subdomains, I can access my localhost using a url like “people.matt.dev” or “places.matt.dev”.

To set up these urls you will need to make some entries in your hosts file. Your hosts file is located at “C:\WINDOWS\system32\Drivers\etc\hosts”. I’ll assume that if you’re running Visual Studio under something other than Windows you already know how to get to your hosts file. Open the file with a text editor like notepad. You will see that an entry like this is already there for localhost:

hosts
127.0.0.1 localhost

Underneath this entry you can add your own urls that will point to your local web server. Like this:

hosts
127.0.0.1 people.matt.dev
127.0.0.1 places.matt.dev


Once you’ve saved your changes to the hosts file, your urls should point to your local webserver.

Finally, if you’d like Visual Studio to use your new urls when opening a website in the debugger, open right click on your project in the Solution Explorer and choose “Property Pages” (what’s the difference between “Properties” and “Property Pages”? That’s just one of life’s little mysteries). Choose “Start Options” and then “Start URL:”. Now you can enter the url you would like the site to start at when you open it in the debugger.

Property pages

And just for fun, here’s a Ruby script that will do most of this for you.

Spring Exploring Time

May 4th, 2008

The warmth means that it’s time to get back out and explore some places. So far, it’s been a few hospitals this month.

There Will Be Blood

I'm melting!

Take a seat

What's that?

Can you handle it?

Hospitals

Textmate Paste History

December 15th, 2007

TextMate has a neat paste history feature that allows you to stack copied text in a queue and then paste the text back into the editor sequentially or out of order.

To try it out, select a section of text and choose “Copy” from the Edit menu or hit Command + C (⌘C). Then select another section of text and copy again. Now you have two items in the queue. To paste the first item the queue, choose “Paste” from the Edit menu or hit Command + V (⌘V). This is the normal pasting behavior that you’re probably used to.

To take advantage of your pasting history, choose “Paste Previous” from the Edit menu or hit Shift + Command + V (⇧⌘V). You have now pasted the very first item that you copied, and the paste history has moved backward in the queue. So, if you were to choose the regular paste command again, it would paste the first item in the list, instead of the second.

To move forward to the second item again, hold the option key and choose “Paste Next” from the Edit menu or hit Option + Command + V (⌥⌘V). Now the second item has been pasted and the queue has moved back to the second item again.

Now let’s say that, instead of 2 items in your list, you had 10 items in your list. You probably wouldn’t want to move backward and forward through the whole list of items every time you wanted to paste something. From the Edit menu choose “Paste From History” or hit Ctrl + Option + Command + V (^⌥⌘V). You should be presented with a menu like the one below.

Scroll through the list and paste hit return to paste one of the items from the queue.

Flickr stats under construction gifs

December 14th, 2007

Flickr just added stats to pro accounts yesterday. I’m still waiting for them to process my account. What’s fun is that they give you a little “under construction” page while they’re collecting your stats.

There are a few different variations and they all have a nice 1990s style animated gif. So far, it looks like there are 4 variations. It’s kind of fun and kind of annoying at the same time.

Dear Microsoft, please take good care of SubSonic

December 12th, 2007

Now that Microsoft has hired Rob Conery from the SubSonic project I’m hoping and praying that Microsoft will put as least as much energy behind SubSonic as they put behind their own .NET projects.

Today, I needed to add another filter to an existing query that was created with a popular ASP.NET ORM that will remain nameless (it’s not SubSonic). I started by trying to decipher the 30 or so lines of code that created the query, but after around an hour of screwing around with it, I had made no progress. Finally, I gave up and asked a fellow employee who is more experienced with this particular ORM if he could figure out exactly what I needed to do to modify the query. Another 15 minutes of staring at the screen and we had finally determined what the intent behind the query was, and where I needed to add another line to filter on the field I wanted to filter on. Now, I concede that maybe I’m an idiot, and that’s why I couldn’t figure how to change the query. But my fellow employee is not an idiot and it still took him much longer than I think it should have to make a change to a fairly simple query.

This isn’t the first time I’ve run into problems with this ORM (it’s not even the first time this week—and it’s only Tuesday). Had we (the fellow ORM enthusiasts and I) have known how troublesome it would be, maybe we wouldn’t have chosen it. But when we were first looking for a decent ASP.NET ORM (around 2 years ago) there really weren’t a lot of viable options out there that offered stability and flexibility, and didn’t require hundreds of lines of XML configuration. So we chose it. And we convinced the skeptics that it was great by showing off how much time it shaved off simple CRUD tasks. And, in the end, everyone learned to use it. Even if it meant coding around some of it’s shortcomings.

But now there are options. Really, really good options, like SubSonic. I’ve been following the SubSonic project for while, and I’d love to use it for a new project. The problem is that it’s another new ORM to learn. And while I’m willing to learn it, I can’t guarantee that everyone working with me on a project is going to be willing to or have the time to learn it. It was a big enough hurdle to convince people that our current ORM (as complicated as it is) was the right option. Now that I’ve changed my mind about it, how can I convince people that SubSonic is going to be any better?

I’m hoping that Microsoft will do the convincing for me. Now that Rob Conery is at Microsoft, I’ve sort of taken for granted that SubSonic will be the default model layer for Microsoft’s new ASP.NET MVC framework. But Microsoft already has other technologies (like LINQ) that could be used in the place of SubSonic for database connections. Personally, I don’t think Microsoft offers anything that has as much potential as SubSonic. My hope is that, even though it wasn’t invented at Microsoft, and it’s a open source project, Microsoft will still put some muscle behind SubSonic. Not just development muscle, but maybe a little marketing muscle too. At least the same kind of marketing they use for the rest of ASP.NET. If only so that someday I’ll never use our current ORM ever again.

Snow on Belle Ave and in Welles Park

December 5th, 2007

It’s the first good snowfall this year and I had to go out and get some pictures. I would have gotten more, but my tripod froze up as I was moving it into position and all of my free hand shots turned out horrible.

Belle Ave

Snow!

Welles Park

Snow!

Snow!

Snow!

After the show…

November 13th, 2007

Look at Mother Nature on the run
In the twenty-first century.

Textmate quickie: CSS opacity

November 11th, 2007

Opacity using CSS isn’t supported very well in every browser (particular with one Internet “exploration” themed browser). It’s possible to get opacity right if you know the right people, but personally, I can never remember exactly what I need to do to make it work. Tonight, I was about to look it up once again, but I decided to see what Textmate would do if I typed “opacity” and hit tab, the usual bundle activation key. Sure enough, when I hit tab, Textmate responded by giving me this:

CSS
opacity: 0.5;
-moz-opacity: 0.5;
filter:alpha(opacity=50);

Not only did Textmate give 3 different options for making opacity work, when I changed the first 0.5 value to something else, the other 2 values changed as well. Textmate to the rescue again!

Textmate word completions or almost Intellisense™

November 10th, 2007

At work I use Visual Studio to develop web applications, and I’ve gotten very accustomed to using Intellisense. Perhaps, a little too accustomed. I’ve also been developing with PHP a lot on the side and I usually use Textmate. However, until recently, I hadn’t been using the word completion functionality that Textmate offers for PHP. It’s not exactly Intellisense, but it provides a lot of the same functionality and has really sped up my PHP development time.

There are two types of word completion that Textmate offers for PHP (that I know of). The first type allows you to type a word and then hit a key to scroll through a list of terms match that word. For example, let’s say I have a function in my class called “checkTheFrontDoor”. I don’t feel like typing that function name all the time. In Textmate I can type “$this->c” and then hit the esc key. The first time I hit esc, “$this->c” will change to “$this->checkTheBackDoor”, the name of another function in my class. That’s not what I want. So, I hit esc again. Now Textmate switches the text to “$this->checkTheFrontDoor”. That’s what I want, so I go ahead and keep typing. You can also use word completion to scroll through the names of variables that you have defined and to scroll through built in PHP functions that match the text you have entered.

The other type of word completion that Textmate offers is more similar to Intellisense. Let’s say I was looking for the name of the function that pushes an item onto an array. My guess would be that the function name starts with “array”, so I type “array”. If I just hit the esc key I can scroll through all of the built in functions that start with “array”. There are a lot of them though, so that could be tedious. Instead I can hit alt + esc and get a pop up menu of suggested function names. Even better, when I choose a function name, it will automatically give me a list of parameters that the function accepts. So, for example, if I type “array”, hit alt + esc and then choose “array_push” from the menu, Textmate gives me the following:

PHP
array_push(array stack, mixed var, [mixed ...])

Textmate gives me the name of the function and the parameters for the function and, like most bundles, it lets me tab through each parameter as I put in the values. As far as I can tell, Intellisense doesn’t give you the option of filling out the parameters, so, in some ways, Textmate’s word completion offers even more functionality.

Textmate offers word completion for many other languages in addition to PHP. If there’s a bundle for a language it probably has some form of word completion with the same esc and alt + esc key combinations. If you’re using Texmate for development, make sure to check if it has word completion for the language you’re developing with.

Some CakePHP requestAction….action

November 6th, 2007

I’ve spent the last few months writing a portfolio system for Columbia College using CakePHP. One of the requirements was a template system that would allow students to choose different templates for their personal sites. I thought it would be a nice feature for users to have a template preview page that allowed them to choose a template from a menu and see what the template would look like with their data.

Initially, I built two separate views. One for the displaying the actual live site, and one for displaying the preview of the site. The two views were nearly identical, aside from a small menu bar at the top of the preview page. I didn’t like the idea that the code was repeated, so I thought that an element might be the solution. However, the templating system required some setup in the controller before the view was actually rendered. This was a problem because the template preview page was not in the same controller as the view for the user’s public page. More repeated code.

I started looking into the requestAction method, but I couldn’t find a whole lot of information about it. Some of what I did find was pretty negative. The manual suggests that one of the uses of requestAction is to retrieve data from another controller. I’m not so sure about using it for that sort of thing. To me, it seems like common data retrieval functions should go in the model. But rendering one action inside of another seemed like the perfect use of requestAction.

To create a dynamic preview page, I created a view with the menu bar that I wanted to appear above the site when it was being previewed. Then, where I wanted the templated page to be rendered I used requestAction to call the action that displayed the public site:

CakePHP
$this->requestAction("/$site_url/$preview_path", 
                      array('template_id' => $template_id));

URLs for the site are structured with the student name and the name of the action being called: /student_name/action_name. Using requestAction I can call those urls, which get handled by the public controller. One caveat is that a view called by requestAction will render without a layout. In this case, that was exactly what I wanted, because the preview page was providing the layout for view.

But how does controller choose which template to render? That’s where the second parameter to requestAction comes in. The preview controller sets a template id based on the template the student chooses from the preview menu. The public controller also uses a template id, but that template id is stored as part of the user’s profile. To get the public controller to use the template id from the preview controller, I needed to pass it on somehow. The second parameter to requestAction allows you to pass an array of extra parameters on to the controller being called. Those extra parameters show up under $this->params in the controller being called. On the preview page I pass on a parameter called template_id. In the public controller I check for that parameter and if it’s not present I default to the user’s selected template:

CakePHP
$template_id = isset($this->params['template_id']) ? 
	             $this->params['template_id'] :
		     $this->user['Options']['template_id'];

Aside from the template id change, the public controller behaves like it normally would, allowing the user to see a templated preview of their site.

So far, I haven’t seen any other practical uses for requestAction that couldn’t be better addressed by other features of CakePHP, but I’m curious about what other reasons people can find to use it.