Entries Tagged 'Web Development' ↓

LinkButton as the DefaultButton fix for ASP.Net 2.0

The Problem: I don't like using the ASP:Button control on the ASP.Net Applications that I build. Mainly because I have little control over how they appear and act. The ASP:ImageButton is better, but it requires that I (or someone) make images with the text required - and when going international that work snowballs quickly.

The ASP:LinkButton is my control of choice. I can use CSS to make rollover and hover states, use what ever text I'd like. Out of the box, as long as IE is the browser everything works - but as soon as you try to submit a form with a LinkButton as the default button in FireFox, the form just reloads and any values that were input are lost.

The Investigation: I found several posts and examples, but most of them were for extending the ASP:Button or ASP:ImageButton controls. I also noticed that they were trying to submit the form via a PostBack method and with the LinkButton it just wasn't working.

The Solution The answer was right there in the page's source as sent to the browser. The LinkButton control gets rendered as a link [A] to the browser. All you need to do to cause the button to fire is go to the address in the HREF.

The Code: Add this code to a SCRIPT block in your MasterPage (or better yet, to a seperate .JS page that is linked to your MasterPage).

function DefaultButtonKeyPress(evt, thisElementName) {
if(evt.which || evt.keyCode)
{
if ((evt.which == 13) || (evt.keyCode == 13))
{
// alert('post back href: ' +
document.getElementById(thisElementName).href);
location =
document.getElementById(thisElementName).href;
return false;
}
}
else
{
return true;
}
}

All that code does is send the browser to the location that you'd go to if you clicked the link, but only if you hit the ENTER button when in a TextBox that calls the JavaScript method.

To get your TextBoxes to call that method, you need to add the following method to your project somewhere. (I have a PresentationLayerTools.vb class where I put all this code, you might like it somewhere else).

Public Overloads Shared Sub DefaultButton(ByRef TextBox As System.Web.UI.WebControls.TextBox, ByRef LinkButton As
System.Web.UI.WebControls.LinkButton)
TextBox.Attributes.Add("onkeydown", "DefaultButtonKeyPress(event, '"
& LinkButton.ClientID & "')")
End Sub

All that code does is add a OnKeyDown event handler to fire the JavaScript method above to the specified ASP:TextBox. The method listens for KeyDown events, if if finds one, it checks to see if the Key you pressed was the ENTER - if it is then it send the browser to the location of the ASP:LinkButton's HREF attribute (which, buy default is a call t another ASP.Net controlled JavaScript method that fires off a PostBack; I'm not sure what all else it does, but it works so I'm happy).

Finally, you need to add the following to the code behind for your pages to tell ASP.Net to execute the DefaultButton method above. I suggest doing it during the page's PreRender event; but it could go other places too.

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e
As System.EventArgs) Handles MyBase.PreRender
Page.Form.DefaultButton = LinkButtonLogOn.UniqueID
PresentationLayer.Tools.DefaultButton(Me,
TextBoxEmail, LinkButtonLogOn)
PresentationLayer.Tools.DefaultButton(Me,
TextBoxPassword, LinkButtonLogOn)
End Sub

Please note that you have to add a call to the DefaultButton method for each TextBox you have on your form that you want to submit the form on.

The Conclusion: I hope that makes sense and works for you, it took me a half a day of banging my head as I searched the Web for a fix. This morning after a nice nights rest the answer was obvious; but because I couldn't find any other similar suggestions I figured I ought to post this to help someone else out.

This code has been tested with: IE 7 and 6 on Windows Server 2003 and Windows XP, FireFox 2 on Windows Server 2003, FireFox 2 on OS X 10.4.10, and Safari 2 on OS x 10.4.10. If you try it on other platforms please let me know how it works!

How about an ASP.NET HTTP Handler to keep your CSS visible.

If you develop your ASP.NET sites like I do, your work involves jumping through some hoops to make sure that your site's CSS referenced images are always visible.
The problem stems from ASP.NET's handy '~' prefix to a URL. The presence of the '~' tells the .NET interpreter that the file can be found by starting at the beginning of the Application's URI. Unfortunately, that feature is not available when serving up .CSS files. There are multiple ways to handle the problem, but mine generally involves creating a virtual directory in IIS that mirrors the final Application's configuration to serve up my local or test versions of the site.
I have a co-worker who likes to load up a project and hit the 'Play' button to test and debug. When he does that, he doesn't always get the CSS for the site (usually because the project name is different from the presumed final name and location for the Application). So, I finally took the time to search for a more elegant solution to the problem yesterday.
The solution came from a user at The Code Project, and I had the simple part working in a matter of minutes. The problem came when I began to work on the submitter's suggested 'Better solution.' The better solution utilizes a HTTPHandler in ASP.NET to parse all .CSS files and replace a temporary string with the desired Background-Color HEX Code or, in my case, the proper path for a image's URI.
I failed to notice and make a few adjustments to the Handler that I created in the first steps, and so I'm blogging this lesson now to help to establish a more technical direction for this blog.
The important thing to notice in the final bit of code, is that now the file is no longer a .ASHX (HTTPHandler file extension) but is instead a .CS (or .VB in my case) file that should be in the APP_CODE directory of your Application.
If you do put the Class file in your APP_CODE directory, then the following bit of code for you Web.Config file needs to be modified:

<httpHandlers>
     <add verb="*" path="*.css" type="CustomHandler.CSSHandler, CustomHandler"/>
</httpHandlers>

The last 'CustomeHandler' in the ADD node can be eliminated (if you are using the APP_CODE), or it should be the name of the reference file (.DLL) that contains the Class. Also, if you are using a Namespace in your class, your Namespace should replace the 'CustomHandler' at the beginning of the ADD node's type attribute.
Another thing worth mentioning is that you will also have to modify IIS to get the .NET interpreter to parse your .CSS files. I added the following comment to my Web.Config to help anyone else setting up a site:

  1. Go to the IIS Manager, right click on the Default Web Site (or Web Site or Virtual Directory if you don't want to modify all of them.)
  2. Select the 'Home Page' tab, the click the 'Configuration' button (somewhere near the bottom middle of the screen).
  3. Under the 'Mappings' tab (the default tab), find a existing setting that uses the ASP.NET executible.
  4. Edit the selected setting, but just copy the path in the Executible textbox.
  5. Click the 'Add' button to create a new setting. Use '.CSS' as the file extension, paste the path to the ASP.NET 2.0 Executible, set the Verbs to 'All' (you could probably only use the 'GET' verb, but I'm just being safe) then uncheck the 'Verify that file exists' and click 'OK'

You should now be ready to use your Web Application from any server or URL and you will always get the images from your CSS files!