Sunday, January 22, 2012

ASP.net Routing vs ScriptManager

Recently I had a problem with ScriptManager on a WebForms site where I was also using the ScriptManager.

Suddenly my ASP.net validators stopped working client-side and on Firebug I could read this error:

ASP.NET Ajax client-side framework failed to load.

Crap... what am I doing wrong here!?

It seems that Rounting messes with the .axd files script manager generates so we only need to tell the routing to ignore those:
routes.Ignore("{resource}.axd/{*pathInfo}");

Done!!

Thursday, November 10, 2011

SQL Server 2008 Transactions Usage Template

I must admit I don't use Transactions that much, but the fact is that most of my stored procedures are atomic, i.e. although they may have a lot of code, only one data changing operation (INSERT | UPDATE | DELETE) is done, so there's no need to wrap it on a transaction.

Because I don't use them much, its not always clear to me what's the "best way" of using a transaction. Sure we all know the basics but:

  • Is the transaction always closed?
  • Are we handling the error that caused the transaction to rollback?
  • Are we accurately reporting the error to the caller?

To be able to always answer YES to all these questions without thinking much about it, my friend Rui Inacio dove into Google and came up with a template that can be used as a start point of all your transaction scripts.
 BEGIN TRY
  BEGIN TRANSACTION
  
   -- ADD YOUR CODE HERE --
  
  IF @@TRANCOUNT > 0
  BEGIN
   COMMIT TRANSACTION;
  END
 END TRY
 BEGIN CATCH
  DECLARE @ErrorMessage VARCHAR(4000)
  
  SET @ErrorMessage = 'ErrorProcedure: ' + ISNULL(ERROR_PROCEDURE(), '') + ' Line: ' + CAST(ERROR_LINE() AS VARCHAR(10)) + ' Message: ' + ERROR_MESSAGE()
  
  IF @@TRANCOUNT > 0
  BEGIN
   ROLLBACK TRANSACTION;
  END
  
  RAISERROR (@ErrorMessage, 16, 1)  
 END CATCH

You may change the way you report the error inside the CATCH but for most cases this is what you need.

Sunday, October 30, 2011

Overriding FormsAuthentication for some URLs

Is this for you?

How many times do you need you're website to have both public and private pages?

How many times did you thought that creating virtual directories with specific web.config files was lame?

If you feel the pain and want it to go away, read on!
Also note that although I'll refer a lot to HttpHandlers on this post, everything here (except the route registration) is also true for common web pages.

Be sure to have a look at this

A few days ago I wrote about handling HttpHandlers with ASP.net routing.
I'll refer to those extension methods to register my test handler route, so have a look on that post before continuing.

Now what I need is a way to override the default FormsAuthentication configuration for a specific set of HttpHandlers.

Virtual Folder, web.config and the ASHX files

FormsAuthentication support this out-of-the-box by simply putting the resources with special security concerns on a separated folder with its own web.config file.

So if you want a virtual directory to allow access to anonymous users just add a web.config file with nothing but this in it:


 
  
   
  
 

This will work for any resource can can be accessed through an URL but this isn't always the case with HttpHandlers.

FormsAuthentication and HttpHandlers without ASHX file

Using the extension methods I wrote on the said previous post you can create an HttpHandler by simply creating a new class and implementing the IHttpHandler interface and point a route to it, just like this:
RouteTable.Routes.MapHttpHandlerRoute("Test", "Unsecured/Controllers/Test", new MyApplication.UnsecuredHandlers.MyUnsecuredHandler());
This means that, whenever you call ht**://mydomain/Unsecured/Controllers/Test the request will be routed to MyUnsecuredHandler instance, not to a physical uri location as usual.
Now have a look at the route. It begins with Unsecured right? Keep reading and you'll understand why.

But we're not there yet, what I really want is to say that some of my handlers allow anonymous requests, and for that I'll edit my website web.config and add the following:


 
  
   
    
   
  
   

Now its done!
Notice that on the location path I only have unsecured. This will grant request permissions to all routes that begin with unsecured!
This is great because now I don't have to bother about structuring the resources on virtual directories and possibly duplicating the code for different scenarios.
Whenever I need a Page or and HttpHandler to be available to anonymous users I just need to create a route to it that begins with unsecured.

If you don't like this approach (specially for pages where the url is visible for the users) you can always add as much location entries on the web.config as you like.

If you're not using Routing you can still specify a location to your resources putting the uri of the Page or HttpHandler on the path attribute:


 
  
   
    
   
  
   

Saturday, October 22, 2011

PubSub with JQuery (Events)

What is PubSub?

PubSub stands short for Publish/Subscriber and is a technique based on events that lets you decouple the logic of an application.
The basic concept is to have something that triggers an event (the publisher) and have one or more listeners (the subscribers) that are waiting for that event to be fired to act appon.

When to use this?

The short answer is: UI Decoupling. Sometimes sections of a webpage must communicate with each other, react on each other activities. To do this we usually have to make the sections aware of each other, making it much harder to maintain.
Using Pub/Subs we just publish the events and forget about it, "someone" else on the page may make some use out of it.

How does it work?

The concept is pretty easy to understand and the implementation follows the simplicity.

The Publisher

This guy here usually reacts on an action and screams out loud:

"I got something here, it's called [myevent] and comes along with this extra information.
Anyone interested?"

$(document).trigger('myevent', [age]);

The Subscriber

This guy meaning of life is to wait for someone says he got a [myevent].
There can be as many guys as you want waiting for the same event, and each can react differently.
 $(document).bind('myevent', function(e, age){ });

Sample Code

Bellow you find a piece of code that shows the functionality in action on a very simple scenario.
Basically you have a textbox where you can enter numbers, meaning ages for the case.
Every time you click on the publish button, an event is triggered, publishing a message that contains the typed age.
Listening are two subscribers that want to be notified whenever that event is triggered.
One of the subscribers only cares about ages bellow 18, the other one cares about everything else.

Create a new html file and paste this code there and show it on a browser. You'll need internet connection as I'm using Google's CDN to get JQuery.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
 <title>JQuery PubSub Demo</title>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
 
 <style type="text/css">
  .Subscriber{ display:block; list-style-type: none; float: left; width: 200px; border: solid 1px #dcdcdc; margin: 5px; padding: 5px; }
 </style>
</head>
<body>
<h2>Publisher</h2>
<p>
 Publish: 
 <input id="txtPublisherAge" type="text" />
 <input type="button" value="publish" onclick='Publish($("#txtPublisherAge").val())' />
</p>

<h2>Subscriber</h2>
<ul id="ulLessThan18" class="Subscriber"></ul>
<ul id="ul18Plus" class="Subscriber"></ul>

<script type="text/javascript">

 $(document).ready(function(){
  
  // handle ages < 18
  $(document).bind('myevent', 
   function(e, age){
    if(age < 18) {
     $('#ulLessThan18').append('<li>Handled age: ' + age + '</li>'); 
    }
   });
   
  // handle ages >= 18
  $(document).bind('myevent', 
   function(e, age){
    if(age >= 18) {
     $('#ul18Plus').append('<li>Handled age: ' + age + '</li>'); 
    }
   });
   
 });

 // Everytime this method is called, the 'myevent' event is published with the passed age value
 function Publish(age){
  $(document).trigger('myevent', [age]);
 }

</script>

</body>
</html>

Cheers

Friday, October 21, 2011

ASP.net 4.0 HttpHandler Routing Support

I'm a big fan of ASP.net Routing and I use it a lot on my ASP.net Webforms applications.

If you're just getting started with Routing on ASP.net Webforms I recommend reading this post from Scott Guthrie.

Ok now, back to the subject, one thing about Routing is that it doesn't support routes that point to HttpHandlers (common .ASHX files).

The code bellow comes just to overcome this limitation by adding a new method (and one overload) to the RoutesCollection object that will let you map a route to an *.ashx url or directly to the handler object.

Edit (2011/11/03): I just updated this due some problems when reusing the same handler for different requests. Now each request gets its own handler like it should.

The Code

namespace System.Web.Routing
{
 public class HttpHandlerRoute<T> : IRouteHandler where T: IHttpHandler
 {
  private String _virtualPath = null;

  public HttpHandlerRoute(String virtualPath)
  {
   _virtualPath = virtualPath;
  }

  public HttpHandlerRoute() { }

  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
   return Activator.CreateInstance<T>();
  }
 }

 public class HttpHandlerRoute : IRouteHandler
 {
  private String _virtualPath = null;

  public HttpHandlerRoute(String virtualPath)
  {
   _virtualPath = virtualPath;
  }

  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
   if (!string.IsNullOrEmpty(_virtualPath))
   {
    return (IHttpHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(IHttpHandler));
   }
   else
   {
    throw new InvalidOperationException("HttpHandlerRoute threw an error because the virtual path to the HttpHandler is null or empty.");
   }
  }
 }

 public static class RoutingExtension
 {
  public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
  {
   var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(physicalFile));
   routes.Add(routeName, route);
  }

  public static void MapHttpHandlerRoute<T>(this RouteCollection routes, string routeName, string routeUrl, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null) where T : IHttpHandler
  {
   var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute<T>());
   routes.Add(routeName, route);
  }
 }
}

How to use it

// using the handler url
routes.MapHttpHandlerRoute("DoSomething", "Handlers/DoSomething", "~/DoSomething.ashx");

// using the type of the handler
routes.MapHttpHandlerRoute<MyHttpHanler>("DoSomething", "Handlers/DoSomething");

And that's it! :)

Tuesday, August 23, 2011

VS 2010 TFS Solution CheckIn Hotkey

Intoduction

This is a nice implementation of a keyboard shortcut to checkin your Solution that makes use of the Macro engine of visual studo.
This implementation will prompt the exact same modal window that shows when we choose "Check In..." from the solution context menu.

This is particulary useful not only on big solution where you have to scroll a lot to see the solution node but also when the solution context menu gets so big that finding the "Check In..." option is not that easy.

Creating the Macro

There isn't any out-of-the-box way of doing this, so we have to write a macro.
On Visual Studio go to: Tools > Macros > Macro Explorer

On the right side a new pane appeared showing the Macros you have.
By default you have two child nodes under Macros: MyMacros and Sample.
Lets use MyMacros.
  1. Right-click it and choose "New Module".
  2. Name it TFS and ckick Add.
  3. Open the created module and replace the entire file content with the code bellow
  4. I don't take the credit of the code bellow, it was taken from here
    Imports System
    Imports EnvDTE
    Imports EnvDTE80
    Imports EnvDTE90
    Imports EnvDTE90a
    Imports EnvDTE100
    Imports System.Diagnostics
    
    Public Module TFS
    
        Sub CheckInSolution()
            DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
    
            Dim fi As System.IO.FileInfo = New System.IO.FileInfo(DTE.Solution.FullName)
            Dim name As String = fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length)
    
            DTE.ActiveWindow.Object.GetItem(name).Select(vsUISelectionType.vsUISelectionTypeSelect)
            DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.TfsContextCheckIn")
        End Sub
    
    End Module
    
  5. Save the Macro and close it.

Creating the Keyboard Shortcut

  1. Go to Tools > Options > Environment > Keyboard
  2. On the listbox searck for Macros.MyMacros.TFS.ChackInSolution and select it
  3. On the Shortcut keys textbox I used: Ctrl+Shift+K, Ctrl+Shift+I
    • This combination is accomplished by pressing K and then I while holding (without releasing) the Control and Shift keys
    • The above combination was available on my environment, don't use a combination that is already in use on your environment.
    • EDIT: I previously had a Ctrl+C, Ctrl-I combination but using Ctrl+C will mess the default clipboard Copy shortcut. If you find that your shortcut messed up anything you must reset the key assignments ckicking the Reset button.
  4. Click OK, and you're done.

Now, when you use Ctrl+C, Ctrl+I anywhere on Visual Studio the checkin modal form will appear just like it would if you choose "Check In..." from the Solution context menu.

Have fun!

Thursday, August 11, 2011

How to strip down or parse an Url using C#

Many times I need to get the segments of an Url, and I'm not only talking about the query string.

If we search around the web we can see a lot of ideas for parsing URLs, most using regular expressions.
The fact is that .net Framework gives us a much better tool: System.Uri.

So if we have an Url that we need to strip down we can write:
public void MyMethod(string url)
{
	System.Uri path = new Uri(url);
	var protocol = path.Scheme;
	var host = path.Host;
	// See the System.Uri documentation for the available methods
}

Note that this object is the same that you may be familiar with and is used when we get the current HttpContext url:
System.Web.HttpContext.Current.Request.Url