Tuesday 21 July 2009

ASP.NET Web Forms – Page Loading Twice

Here’s an obscure bug, I had a page that was loading twice and I had no idea why.  Most internet answers just say “Turn AutoEventWireup to false” without understanding why it might legitimately be set to true or even trying to understand why it could or should be set to true, it’s VERY frustrating.  Well I did finally find out why it does this.

Far as I can tell it’s a bug, but there might be a very good reason behind it that I just don’t know or understand.  If you have an image with an SRC attribute set to “” then the page MAY load twice.  Sounds ridiculous right?

Well this:

   1: <img src=""/>
Will force your page to load twice.  It’s a very bizarre way of handling it.

Ajax Script Handlers in IIS 7 (jQuery, Ajax, ASMX)

There’s a fair bit of information about how to get jQuery to work with ajax calls to ASMX files using JSON.  There are lots of ways to do it, and most of it is specifically focussed on IIS 6.  Well I came across a couple of problems in IIS 7 when trying to deploy an ajax script that could consume an ASMX web service.

One thing that you will need to do is enable the HTTP handler for ajax and ASMX.  In IIS 6 this is different from IIS 7, but it can be really hard to find the correct resource on how to do it correctly with IIS 7.

In IIS 6 you do something along the lines of:

   1: <httpHandlers>
   2:  
   3: <remove verb="*" path="*.asmx"/>
   4: <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
   5:  
   6: </httpHandlers>
However IIS 7 has changed a little and you’ll need to define your script handler more like this:

   1: <system.webServer>
   2:         
   3:     <handlers>
   4:     
   5:       <remove name="ScriptHandlerFactory"/>
   6:       <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   7:     
   8:     </handlers>
   9:  
  10: </system.webServer>

I’m sure most of you know this already, but IIS 7 is relatively new to me compared to IIS 6 so this took me a while to find.

Monday 13 July 2009

Speech Bubbles with CSS Only

Ok so these aren’t really new, most of them use images to get them to work but if you’ve ever worked with private banding of your site then images are very difficult to work with.  I wanted a solution that uses CSS only and the sites and examples I found weren’t quite sufficient, so I figure I’ll blog how I produced my own.

The first trick I learned is to make a triangle shaped div.

div.speechBubbleTickLeft 
{
    position: absolute;
    width:0;
    height:0;
    border-left: 0px solid transparent;
    border-right: 15px solid transparent;
    border-top: 15px solid #00aff0;
    border-bottom: 0;
    margin-left: 20px;
    margin-top: 0px;
}

This will show a tick on the left side, like this

image

Then all we need to do is place is at the bottom of your text div.  If your divs are a single colour, then this is a peice of cake.  But if you have a solid single border around your div then this gets harder.  You will need to fill your triangle with another triangle that is a pixel smaller to get your border.

div.speechBubbleTickInnerLeft 
{
    position: absolute;
    width:0;
    height:0;
    border-left: 0px solid transparent;
    border-right: 13px solid transparent;
    border-bottom: 0;
    margin-left: 21px;
    margin-top: 4px;
}
image

Now just add your favourite styling to your div’s and you have yourself a nice speech bubble.

image

You can also make your speech bubble ticks go right, left or center just by adjusting the border-left and border-right properties.  It works in every browser I can test on, I.E. IE7, Opera, Safari, Firefox, Chrome.

Friday 3 July 2009

Asynchronous Posting with ASP.NET, JQuery and Ajax

This is much easier in ASP.NET MVC (or at least I thought so), but I’m not currently working on an ASP.NET MVC site but a, dare I say it, classic ASP.NET site.  No I don’t want to discuss that web forms and ASP.NET is old, I merely mean that the site I’m working on is a more regular style ASP.NET site.  The site would have been well suited to ASP.NET MVC had it been available when it first came to life, but none the less it’s what I’m working with and it’s far from painful.

However with the web forms way of working many of the existing pages make postback calls to the server.  This is a very easy way to work, but it’s not pretty.  We also tend to avoid server side controls and in particular the whole server side Microsoft Ajax Toolkit (which I’m thankful for) even though it would make much of this form posting more “pretty”.  So I figure the easiest way to get an asynchronous post done on the client side was to use jQuery and Ajax.  I love jQuery.

I had thought this would be a fairly standard thing to do, and it might be, however I found it hard to find accurate and useful information.  There are many many ways to do this. 

You could use a web service and just make a call to the web service with jQuery, however this application doesn’t implement any services yet so that seemed like something I didn’t want to do.

You can make a "[WebMethod]” and call the web method using the $.ajax object in jQuery, but as the call I wanted to make was from a user control I wanted the method to be removed from the aspx pages.  So I settled on a web handler, an ashx file.  There were already some of these in the application, so it was a sensible choice. 

JQuery

First the jQuery part.  This is very simple really.

   1: $.ajax({
   2:     url: "ReviewHandler.ashx",
   3:     data: {
   4:         name: $("#ReviewerName").val(),
   5:         location: $("#ReviewerLocation").val()
   6:     },
   7:     processData: true,
   8:     type: "POST",
   9:     beforeSend: function() { startSubmit(); },
  10:     complete: function() { submitComplete(); },
  11:     error: function(xhr, statusText, errorThrown) { alert(errorThrown); },
  12:     success: function(data) { submitSuccess(data); }
  13: });

I’ve found a few sites that suggested how to do this.  The biggest area of difference was in the data section.  I think this depends on the data type you’re going for, but in my case I’m after the most simple implementation so I’ve not specified one.  This format will place the name/value pairs into the query string.

Most of the sites I found showed the jQuery side, very few of them showed the implementation on the C# side.  I’ve created a generic handler called ReviewHandler.ashx.  By default it creates a ProcessRequest method (with weirdly placed braces in the template), and you’ll use this to process any requests to the handler.  Here’s mine:

   1: /// <summary>
   2: /// Process the Ajax request from the web form.
   3: /// </summary>
   4: /// <param name="context"></param>
   5: public void ProcessRequest(HttpContext context) 
   6: {
   7:     if (context.Request.RequestType.Equals("POST"))
   8:     {
   9:         context.Response.ContentType = "text/plain";
  10:  
  11:         string name = context.Request["name"];
  12:         string location = context.Request["location"];
  13:         
  14:         // Process the data.
  15:  
  16:         context.Response.Write("My Output");
  17:     }
  18: }

Of course I want to be secure so I’m only handling post methods, any get methods are ignored by the handler.  You could also implement a client side captcha as well if you are concerned about bots using your service, but I’m not going to cover that here.  If anyone happens to read this and has any suggestions, please let me know.  While this works really well, it’s a bit awkward having to investigate the query string to get the parameters and I’m SURE there is a better way.

Wednesday 1 July 2009

Centre aligned web pages and vertical scroll bars

If you have ever had a website that has a centre aligned div then you know the pain of scroll bars.  I’ve always wished that browsers would reserve space for scroll bars so that your content was not affected.

Seems like the way to go about making your pages sit still is the force the vertical scroll bar into existence.  It’s not great, but fortunately it’s really easy.

html 
{
    overflow-y: scroll;
}
This simple CSS entry will enforce the scroll bar.  It works in everything from IE6 to Chrome (including Safari, Opera and Firefox).  I’m certainly not the first person to blog about this, but I figured it was worth posting about anyway.  What I want to know is, is there a better way?!?