Thursday, September 18, 2008

Dynamic Drop-Down Menus in ASP.Net 2.0 / 3.5

One of the most essential components to a solid site is a versatile and intuitive navigational drop-down menu. There are many ways to do this. My goals, as always, when approaching a challenge:

  1. Let's not reinvent the wheel.
    There are many solutions out there. A big point of the .NET Framework is to provide reusable components so that you don't have to code things from scratch. Chances are it's already been developed and developed well.

  2. Avoid hard-coding where possible.
    It's all HTML, CSS, and Javascript by the time the menu renders in your browser, but that doesn't mean you need to code it in that way. We're trying to build something dynamic and avoid duplicating code from page to page. That means there is going to be a data feed, whether from XML or a database, and a control that can process and display this feed from page to page.

  3. Create an elegant, cross-browser compliant solution.
    Some of the out-of-the-box ASP.Net menu controls are not that pretty and don't really work across all browser platforms, especially Safari (Webkit based... speaking of which - guess what Google's Chrome uses ;-) ) We need something that will be readable, easy to maintain, and most importantly, work across all browsers.
I found a couple of methods out there to accomplish this. Peter Bromberg talks about one way in his blog here (http://www.eggheadcafe.com/tutorials/aspnet/f4bf9b1a-c934-43be-b026-9f3443fc87c9/build-an-aspnet-20--xml.aspx).

It's a variation of an ASP.Net 1.1 solution previously published in 2003 by WROX. It works, but it's a slight modification from the 1.1 version, and it seemed a little cumbersome to customize the look and feel, so I continued to look for something designed specifically for 2.0 and up that would be simple to use out-of-the-box and easy to customize.

Surely enough, I stumbled upon a solution that met my three goals, written by ScottGu (http://weblogs.asp.net/scottgu/archive/2006/05/02/444850.aspx)

To build a drop-down menu, we need the following:

  1. Data Feed
  2. CSS Stylesheet
  3. Server-side control that will generate a menu from #1 and #2.
The data feed is your standard web.sitemap (http://msdn.microsoft.com/en-us/library/system.web.sitemap.aspx) that you can build in Visual Studio that looks something like this:


<xml version="1.0" encoding="utf-8" ?>

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

<siteMapNode url="" title="" description="">

<siteMapNode url="" title="" description="" />

<siteMapNode url="" title="" description="" />

</siteMapNode>

</siteMap>


The server side control is our typical with a SiteMapProvider, which is just responsible for reading in the data feed - in this case our web.sitemap file.

The CSS is the tricky part. Using out-of-the-box simplified customizations won't get you your desired result, and if it will, chances are it probably won't look the same from browser to browser. Our solution:

CSS Control Adapter Toolkit for ASP.Net 2.0
You can download it here: http://www.codeplex.com/cssfriendly

The toolkit essentially takes the worry out of coding for cross-browser compliance by providing ASP.Net controls that are already formatted in CSS to look pretty and the same in all common browsers, which is fantastic, because usually, you have to buy a component like this.

For our drop-down menu, you can do vertical or horizontal; it uses CSS best practices by utilizing ul/li's instead of tables.

Check out ScottGu's blog to get the code, documentation, and a more detailed explanation of exactly how to build, install, and use the drop-down menu with the CSS Control Adapter Toolkit.

As always, I welcome your comments.

UPDATE - 9/22/08
As it turns out, the vertical menu doesn't display the sub-items properly in IE6. That doesn't work for me as more than 45% of my user base is on IE6. Stay tuned and I will post a fix for it.


Applies to:


Wednesday, September 10, 2008

Making use of the 'Drop" in Drag-and-Drop in ASP.NET/AJAX

I find it a lot when developers get asked what is AJAX, a very common answer is - it's that technology that let's you drag and drop things without leaving the page.

Working within the .NET 2.0 or the 3.5 framework, there is functionality in the AJAX toolkit that let's you drag things using the DragPanel control in the AJAX control toolkit (http://www.asp.net/AJAX/AjaxControlToolkit/Samples/DragPanel/DragPanel.aspx). Very cool stuff if all you are trying to do is allow the user to reposition things. If you are trying to extend it for a more practical use, like being able to drag an item to a shopping cart, you don't really get that functionality out of the box with the AJAX control toolkit.

Looking at our objective from a 64,000 ft. view, we have this "hot" zone somewhere on a page. We have a couple of objects that can be dragged onto this zone, and when that happens, we want to be notified exactly what was dragged and to which zone, so that we can fire the appropriate code, such as add the object to our shopping cart.

How do we accomplish this given that this functionality is non-existent in the AJAX control toolkit? I was asking myself this question until I ran across a very cool solution by Jeff Prosise who writes for a section in the MSDN Magazine called Wicked Code. You can subscribe to it here: http://msdn.microsoft.com/en-us/magazine/rss/?col=Wicked%20Code

The caveat with his solution is that it uses the Microsoft.Web.Preview library which comes as part of ASP.Net Futures (downloadable from here - http://www.microsoft.com/downloads/details.aspx?FamilyId=A5189BCB-EF81-4C12-9733-E294D13A58E6&displaylang=en). The official description of the ASP.Net Futures is "Contains features currently being considered for future versions of ASP.NET and the .NET Framework," meaning you probably won't find too much documentation or support for it... or a guarantee of any sort that it will be included in the next release of the .NET Framework.

There is the fine print. If you are planning on deploying this to a high volume enterprise environment, it's certainly something to think about, however, Jeff's solution looks elegant, robust, and customizable to fit your need.

The code, article, and documentation is available here:

Great work Jeff!
Applies to:

Saturday, September 6, 2008

Windows 2008 Server - Vista Alternative for your Desktop

This is a little bit off topic, but needed to be written...

If you like the aesthetics of Windows Vista, and, unless you are short on CPU, memory, or video resources, there is no reason not to, you have had debates with yourself. The almost-too-common debate of whether you should downgrade to XP or stay with Vista and deal with the errors, bugs, and problems... because it's just a pretty OS. So how do you get beauty AND brains without going to the Mac store?

Microsoft Windows 2008 Server
It's just like Vista, without the stupid bugs

Yes - that's the slogan they are going with.

I recommend this for any users running Vista on their desktops. The reason I don't recommend it for laptops is you won't get the best battery utilization and you won't have the options of putting your OS to sleep or hibernation.

To get Windows 2008 Server to act like a workstation, it will take some configuration to make it more user-friendly, and less like a server. I was referred to a blog that gives step-by-step instructions on accomplishing this:
http://www.win2008workstation.com

If you have 2 days to spare, I recommend you try this out. Unless you upgrade from 32-bit Vista to a 64-bit Windows 2008 Server, most of your Vista drivers should work without a problem.

Use Macrium Reflect (click for free download) to ghost your current image, in case you want to go back.

To download the trial evaluation, check out:
http://www.microsoft.com/windowsserver2008/en/us/trial-software.aspx

Applies to:
, ,

Friday, September 5, 2008

Workaround to AuthenticationService security issue over HTTP

It's very convenient to be able to log in on a nice & functional page without leaving to go to a special secure & encrypted login page, hoping to be brought back to the page that you were on with all your work saved.

The AJAX Framework in NET 3.5 provides a web service to help us accomplish that: AuthenticationService (http://msdn.microsoft.com/en-us/library/bb386582.aspx).

If you are already on an encrypted HTTPS page, this works great. However, if you are serving out that nice & functional page over HTTP, because frankly, you don't need images or text encrypted, and would rather not use up overhead just for the sake of a login form, you may have a problem.

Specifying the line below in your web.config won't really do anything.
<authenticationservice enabled="true" requiressl="true"></authenticationservice>

Changing the protocol to HTTPS in your path won't help you either:
<asp:scriptmanager runat="server">
<authenticationservice path="https://localhost/MyAuthService.asmx"></authenticationservice></asp:scriptmanager>

Why? Because it so happens that this version of AJAX, included in .NET 3.5 does not support cross-domain proxy authentication.

So, how do you solve the problem of making sure your user's credentials don't get traced through unencrypted HTTP headers while keeping the page served over HTTP and not redirecting him/her anywhere?

MD5 encryption via Javascript

Before the password gets posted to your ASP.Net form, you encrypt it with MD5. MD5 is a one-way encryption algorithm that cannot be decrypted. To use it, you:
  1. Encrypt the submitted password value.
  2. Encrypt the DB-stored password associated with the submitted email address.
  3. Compare the two values. If equal, you can deem the authentication successful.

With no need to reinvent the wheel, I found a great script for encrypting strings into MD5 format here:
http://pajhome.org.uk/crypt/md5/
Great work Paul!

Conclusion
With the shortcomings of the AJAX toolkit inside of .NET 3.5 Framework, Visual Studio 2008 is still a great IDE and before you go switching to PHP, all it takes is some time, creativity, and improvisation.

Is it safe to use client-side encryption?
Yes. Our goal is to prevent the HTTP headers from being compromised or traced in midstream, before they get to the server they are going to. As long as you are on a browser that supports JavaScript, Paul's MD5 function should do the trick.

I will post some code later. I welcome your feedback.



Applies to:
, ,