Andornot Consulting Inc.
Home Page
Home Page
 |  | 

Thursday, June 28, 2007

ResolveUrl vs. ResolveClientUrl

The .NET Control class methods ResolveUrl and ResolveClientUrl both take a relative URL as a parameter and return relative URLs for client browser use. So what's the difference between them?

In simple terms, ResolveClientUrl returns a path relative to the current page, and ResolveUrl returns a path relative to the site root. Both methods are particularly useful when passing in a relative URL prefaced with the tilde (~) to indicate the application root.

Let's say we have an image in a layout directory, and a page which needs to pass a usable relative URL for the image to the client browser.

image http://www.andornot.com/layout/images/andornotLogo.gif

page http://www.andornot.com/Products/Default.aspx.

Here is what we would get if we called the two methods from our Default.aspx page.

Page.ResolveUrl("~/layout/images/andornotLogo.gif")
"/layout/images/andornotLogo.gif"
Page.ResolveClientUrl("~/layout/images/andornotLogo.gif")
"../layout/images/andornotLogo.gif"
There is more to it, of course, particularly since these are Control methods, not exclusively Page methods. It's pretty straightforward to see how paths relative to a page resolve, but not necessarily so obvious when the control is being instantiated in a UserControl or MasterPage.

ResolveUrl uses the Control.TemplateSourceDirectory property to do its job, and that property value is the virtual directory of the Page or UserControl that contains the current server control.

ResolveClientUrl returns a URL relative to the folder containing the source file in which the control is instantiated.

Labels: ,

Public Hotfix Patch Available for Debugging ASP.NET on IIS7

Mentioned first a couple posts back, there is now a public hotfix patch available for debugging ASP.NET on IIS7 that you can download here. The reason for this post is that Scott Guthrie just wrote a post that gives a much better explanation of the problem and fix.

Labels: , , ,

Wednesday, June 27, 2007

Type-safe access to the current page's URL

Virtually every web project you work on requires that you get the current page's complete URL. Years ago, I got tired of using non-type-safe ways of munging together various Request.ServerVariables to get it (anyone remember stuff like "If Request.ServerVariables("HTTPS") = "on" Then..."?) and with .NET there had to be a better way. Due to a dearth of non-Request.ServerVariables examples out there back then, it took trusty trial and error Response.Write tests and the MSDN help to settle on the following:

Request.Url.Scheme + Request.Url.SchemeDelimiter + Request.Url.Authority + Request.Url.PathAndQuery

While I never understood why I still had to parse these together (and I sporadically investigated alternatives), it nevertheless felt so much better than parsing together strings like "://" with icky stuff like Request.ServerVariables("SERVER_NAME").

But yes, there had to be an even better way: a way that resisted forgetfulness and the ensuing battle with more than vague intellisense descriptions. Since I'm slow, it was only today that I found it. My my, sometimes I do miss the obvious:

Request.Url.ToString()
returns the canonically unescaped form of the URI (i.e. "http://www.example.com:80//thick and thin.htm")

and/or

Request.Url.AbsoluteUri
Returns the canonically escaped form of the URI (i.e. http://www.example.com:80//thick%20and%20thin.htm)

And yes, I had tried out AbsoluteUri before (I must have, right?), but for some reason, I still missed it.

Labels: ,

Friday, June 22, 2007

Testing websites locally on Vista Part II

Peter beat me to the post already, but instead of just leaving these thoughts in the comments, I figured I should add my two cents in a dedicated post as there a couple other things to take note of if a) you're not running as an Admin in Vista and/or b) you want to debug easily with Vista and IIS7.

First off, before hitting Peter's post, go to ScottGu's post. It tells you the essential step of making sure you've installed the "IIS 6 Management Compatibility" option within IIS7 (as ScottGu states, it "installs an API for the new configuration system that is compatible with the old Metabase APIs (which is what VS 2005 uses)").

As well, it'll help you if you've continued to run as a non-Admin on Vista with UAC enabled (both Peter and I have given up on this and are running as Admins with UAC off - the horror). I attempted for a month or so to use Vista with UAC etc., but the deal breaker was when I discovered that I couldn't drag and drop files into Visual Studio; nor could I open a project using the sln file. I'll hold off on UAC until stuff like Visual Studio is upped to use it reasonably (however, for those that want to use this as another reason to slam Vista, my love-hate relationship continues, but whenever I have to do something on my WinXP machine, I cringe...thus, there's a whole lot more love right now than hate).

In addition, I've found that in order to enable debugging, I need to add the following two steps:

  1. Set your application pool for the site to the Classic .NET AppPool.
  2. Enable Windows Authentication so that you can debug the site (haven't taken the time to figure out why this particular combination works, but suffice it to say, out of all the posts out there explaining how to get going with debugging with IIS7, this is the only thing that really matters). You'll get a "Challenge-based and login redirect-based authentication cannot be used simultaneously" alert, but ignorantly ignore this and you'll be fine.

UPDATE: I just found out in the writing of this post, that there is now a Visual Studio patch that fixes the Visual Studio F5 debugging of IIS7Applications on Vista.

NOTE: I LOVE being able to run multiple sites at one time. Bliss!

Labels: , , ,

Wednesday, June 20, 2007

Testing websites locally on Vista

Now that Vista is here with IIS 7, and can set up multiple websites, I have no more need of the IISAdmin tools I used with Windows XP, which hacked IIS 5 to allow more than one website (the limitation being only one website active at any given time).

I've got a pretty good system going.

1. I set up a website for a client project and assign a host header that resembles the client domain:

CropperCapture[12]

2. I open my hosts file (%WINDOWS%\system32\drivers\etc\hosts) and bind the new host header to the local server loopback address:

127.0.0.1     localhost-foo.clientsite.com

3. If I'm working with an ASP.NET website or web application (which is 99% of the time) I tell the Visual Studio 2005 project to use the IIS webserver at the just-defined host header when viewing and debugging:

CropperCapture[11]

It all makes for a realistic representation of how the application or website will behave on the client's domain, allowing me to be sure that various relative URLs are going to resolve, for instance. It is often the case that I am working with a predefined website hierarchy and template, so it's important to emulate the client's site as closely as possible, so that deployment is less of a hassle.

Labels: , ,

Friday, June 15, 2007

How to install Inmagic DB/Textworks on Vista

Right-click on the db/textworks installer. Choose "run as administrator". You may be prompted to proceed and/or enter administrative credentials, depending on your Vista setup. The installer will start installing and should work fine.

If you do not run as administrator, you will get an error like this:

Error 1925. You do not have sufficient privileges to complete this installation for all users of the machine. Log on as administrator & retry installation.

You may be confused by this message if you are logged in as an administrator. Welcome to Vista's User Account Control (UAC).

With UAC, you may have logged in as an admin, but you are not running as one. Instead you are prompted to elevate your permissions whenever you attempt an administrator-level operation. It so happens that Inmagic has not updated db/textworks to handle this scenario and give you fair warning. The error message it gives upon failure is at least completely accurate in its diagnosis, but leaves it up to you to manually elevate your permissions.

Here are some other Inmagic-on-Vista related posts on the Andornot Developer Blog:

Labels: , ,

Thursday, June 14, 2007

Windows Home Server

Woo-hoo! I'm in the RC1 release for Windows Home Server.

It's kind of like a SAN (storage area network). For at home. Added hard drives donate their space to the pool. If there are two or more hard drives involved, duplication can be enabled.

Plus more: centralized backup, file sharing, printer sharing, remote admin, remote access to PCs, health monitoring, media streaming, etc.

Over the past few years I've been unsatisfied with the various network devices I've implemented at home for backups and shared files. I LOVE the idea of an easily configurable server that is expandable and that provides a central administration point for all the home network chores.

Yeah, I could have knocked something like WHS together myself, but I'm lazy and I have limited time. The wife already rolls her eyes and tells me I'm not allowed more than 6 hours of computer love on a weekend.

To sign up for RC1, get on over to http://connect.microsoft.com/WindowsHomeServer real quick.

Wednesday, June 13, 2007

Sometimes if it's complicated, it's probably too complicated: doing noscript tags with JavaScript

A couple days back I implemented ComponentArt's new ComboBox for a project. Worked great and brought some nice functionality (look ahead filtering and linked dropdowns: a second ComboBox populated via an AJAX callback according to the value selected in the first). However, I noticed at the very end that the controls do not degrade AT ALL when JavaScript is turned off. They look the same, but are completely disabled and useless.

At that point, even if I could duplicate the functionality another way it wasn't worth it; at the very least however, I needed to provide obvious notification that if JavaScript is disabled, the dropdowns are completely non-functional. So heh, easy enough: create a div nicely styled with the obligatory "JavaScript must be enabled to...blah blah blah..." and then set up a startup script for everyone with JavaScript enabled so that this message is not visible.... If you aren't laughing right now, you should be.

It took me a couple days to remember that that's what <noscript>fancy "If you don't have JavaScript enabled" message here</noscript> is for.

Labels: ,

Thursday, June 07, 2007

Fixing short date strings in Textworks

The Problem

1000s of date strings in short date format like m/d/yy. Fine as long as system date settings assume month/day/year. Then system date settings change to day/month/year to conform with international standards. 1000s of date strings are misinterpreted.

E.g. 06/01/2007 Before = June 1, 2007 After = January 6, 2007

The Fix

  1. Export date field and unique ID field to delimited text file.
  2. Use regular expression to switch day and month:
    • find expression: (\d+)/(\d+)/(\d{4})
    • replace expression: \2/\1/\3
  3. Import modified file into Excel or Access, treating the date string field as DateTime so it's interpreted as a proper date, not a string.
  4. Change the format of the date field to a Long Date
    • Access query expression: Format([MyDate], "Long Date")
  5. Import the file with long date back into Textworks, matching on unique ID field; replace field values.
  6. Date strings are now in unambiguous Long Date format, e.g. MMM dd, yyyy.
UPDATE: This comic at xkcd.com is totally awesome. And relevant and stuff. comic

Labels: , ,

Wednesday, June 06, 2007

Adding a second virtual drive to a VM

Jeesh. I feel like a dunce. A dunce who just wasted too much time to figure out something I already knew.

The problem: adding a secondary virtual drive to a Win XP virtual machine. No problems adding it via the Virtual PC 2007 console; no problem once booting up the VM having the drive found ("Virtual Drive found and installed"); but big problem in that the new drive is nowhere to be found in Windows Explorer.

Solution:
  1. Right-click My Computer
  2. Manage
  3. Disk Management
  4. Activate the new virtual drive
  5. Give a drive letter and partition
  6. And if you're like me, change the drive letter on your CD-Rom to E: and then switch your secondary hard drive to D:.
To switch the CD-Rom drive letter:
  1. Make sure you maximize the Computer Management window to see all drives listed (as the CD-Rom won’t be listed in the drive volume listing above)
  2. Right-click your CD-Rom and select Change Drive Letter and Paths
  3. Then in the drive volume listing above, select your secondary virtual hard drive and right-click and select Change Drive Letter and Paths.

I guess virtual drives are a little too virtual to instantly become available in explorer ready and waiting for formatting.

What's most painful about this is that all along while googling everywhere trying to come up with the magic search term combination (i.e. "Virtual PC 2007 secondary hard disk" doesn't quite work - I KNOW IT'S A GOOD IDEA TO INSTALL YOUR VM ON A SECONDARY DRIVE!!!), in the back of my mind I'm thinking I should look in Computer and Disk Management...

Btw, If google doesn't work right away and it's Windows related, check out Microsoft's Community Forums.

Labels: ,

Friday, June 01, 2007

No time for Textworks date fields

Ha ha! That was a pun, that was. "No time for Textworks date fields." Phew... that is the kind of half-inflated rubber-mattress-smelling type of humour I am capable of, here on this highly informative forum.

So I discovered the other day, quite by accident, that Inmagic textbase Date fields are exactly that and no more. By which I mean: Date fields are not DateTime fields.

Perhaps on the surface this seems a trivial distinction. Let me assure you, my dear confidant, it is not.

You can enter time information in a non-strict Date field, or one that has trailing text enabled, but the time you enter is just a string. It is not understood as a chronological statement. You might as well type "blah blah blah" instead of "09:00:00 AM" for all the good it does you, because you can't search for, or sort by, time. You and I know that 1:00:00 PM comes after 12:00:00 PM, but Inmagic doesn't.

Here's an example where I told the report to sort by a date field. Note that it is NOT sorting chronologically, but rather, numerically.

CropperCapture[4]

I'm so surprised that there is no way to handle chronological data. In the languages, programming environments, and database systems I work with, it's just assumed that Date fields, classes, and variables are date-plus-time: DateTime objects. The assumption is such that you can call a DateTime object a Date, in fact, and everyone already knows you really mean DateTime but aren't pretentious enough to have to say it. (The javascript Date object is an example off the top of my head.)

A DateTime object can of course show a date without time, but that's just a matter of formatting. The information about time is still in there. And, even if you instantiate a DateTime object with a date string and don't include the time, the time defaults to 00:00:00.

Anyway, I'm not sure what to do about this.