Posts tagged C#

A simple redirect route handler for ASP.NET 3.5 routing

ASP.NET 3.5 Routing is a very powerful tool not just for registering routes for newer ASP.NET MVC applications but also for adding SEO friendly routes to older Webforms (ASPX) applications, or for routing multiple URLs to a single page. But that’s not all it can do. You can create your own IRouteHandler and then have complete control over what to do with any incoming HttpRequest.

Here for example is a way to do a permanent redirect when a given route is matched. To use it you might, for example, do:-

            routes.Add(new Route("sample.aspx", new RedirectRouteHandler("/home/start")));

Here is the RedirectRouteHandler that can turn any request into a 301 redirect for you:-

    /// <summary>
    /// Redirect Route Handler
    /// </summary>
    public class RedirectRouteHandler : IRouteHandler
    {
        private string newUrl;

        public RedirectRouteHandler(string newUrl)
        {
            this.newUrl = newUrl;
        }

        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new RedirectHandler(newUrl);
        }
    }

    /// <summary>
    /// <para>Redirecting MVC handler</para>
    /// </summary>
    public class RedirectHandler : IHttpHandler
    {
        private string newUrl;

        public RedirectHandler(string newUrl)
        {
            this.newUrl = newUrl;
        }

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext httpContext)
        {
            httpContext.Response.Status = "301 Moved Permanently";
            httpContext.Response.StatusCode = 301;
            httpContext.Response.AppendHeader("Location", newUrl);
            return;
        }
    }

Note: I’m not saying this is the best or only way to handle this. You’ll want to look at Url Rewriting and the Application and Request Routing module for IIS7 in particular.

Why functional programming and LINQ is often better than procedural code

Functional programming is a relatively new component in the C# language.  It can potentially replace for-loops in many situations with simpler code, but the question remains ‘what’s wrong with a good old for loop?’

Here are some of the reasons I think functional programming is important and in particular how LINQ can improve the readability, maintainability, and parallelizability (if there were such a word) of your code:

  1. Functional approaches are potentially easier to parallelize either manually using PLINQ or by the compiler. As CPUs move to even more cores this may become more important.
  2. Functional approaches make it easier to achieve lazy evaluation in multi-step processes because you can pass the intermediate results to the next step as a simple variable which hasn’t been evaluated fully yet rather than evaluating the first step entirely and then passing a collection to the next step (or without using a separate method and a yield statement to achieve the same procedurally).
  3. Functional approaches are often shorter and easier to read.
  4. Functional approaches often eliminate complex conditional bodies within for loops (e.g. if statements and ‘continue’ statements) because you can break the for loop down into logical steps – selecting all the elements that match, doing an operation on them, …

These days I opt for the functional syntax more often than not and fall back to for-loops when:-

A. The body of the loop contains complex logic that cannot be disentangled into a cleaner sequential application of functions and it simply easier to just write a for-loop with the complex conditional code in it.

B. The task is inherently not functional, i.e. has side effects

C. The task needs exception handling in it. Sure you can write big lambda blocks with try catch in them but at some point it becomes easier and cleaner just to use a for-loop.

Development Tools and Libraries I use

Libraries and Code Snippets

TweetSharp

Predicate Builder for LINQ query building: http://www.albahari.com/nutshell/predicatebuilder.aspx

Useful tools

LinqPad  http://www.linqpad.net/

Source Control

Subversion with TortoiseSVN

Continuous Integration

JetBrains TeamCity, recently moved off CruiseControl.NET

Deployment

Subversion as a repository for binary images, custom deployment code

Web Server

IIS7

Useful articles

PHP: http://devzone.zend.com/article/627

Putting a feedback button on every page with ASP.NET MVC and JQuery

Feedback button

You’ve probably seen many web sites with the floating ‘feedback’ button down the side. Here’s how to add one to your site using jQuery, jQuery UI and ASP.NET MVC.

First make sure you have jQuery and jQuery UI referenced in your master page view together with the CSS file for whichever jQuery UI theme you have chosen.

We’ll make a few changes to the master page view to add the pop-up feedback form, we’ll add an action on a controller to accept the feedback that is posted, and we’ll need a small amount of CSS.

So, after referencing those javascript files and the theme CSS, the first thing to do is to add the following HTML to the bottom of your master page view:

            <div id="feedbackdialog" style="width:300px; height:300px;text-align:left;">
                <p>Your name and/or email: <br />
                <input type="text" id="feedbackEmail" name="feedbackEmail" size="34" value="<%: this.Model.AccountEmailOrEmpty %>" />
                </p>
                <p>Comment:<br />
                <textarea id="feedbackComment" name="comment" cols="35" rows="5"></textarea></p>
                <br />
                <div id="feedbackResult"></div>
            </div>

Now add this code to your global javascript file that also referenced from your master page view … don’t embed it in the page, go ahead and do the right thing and put it in a .js file so it’s not a burden on every page.

//function for the feedback form
$(document).ready(
    function () {
        /* Create the feedback dialog */

        $("#feedbackdialog").dialog(
        {
            closeOnEscape: true,
            modal: true,
            autoOpen: false,
            resizable: false,
            title: 'Feedback',
            width: 400,
            buttons: { "Send": function () {
                var dlg = $(this);
                $.post("/corporate/suggest",
                        {
                            email: dlg.find("input[name='feedbackEmail']").val(),
                            comment: dlg.find("#feedbackComment").val(),
                            url: document.location.href
                         },
                        function (data) {
                            dlg.dialog('close');
                        }
                );
                $(this).html("<p id='feedBackSending'>Sending</p>").dialog({ buttons: {} });
            }
            }
        });

        $('.contact_us').click(function () {
            $("#feedbackdialog").dialog("open");
            return false;
        });
    });

Next we’ll add the action referenced here, in the example we used the url ‘/corporate/suggest’ so, assuming you have a controller called CorporateController, add the following action to it …

        public ActionResult Suggest (string email, string comment, string url)
        {
            if (!string.IsNullOrWhiteSpace(comment))
            {
                // here we will log the feedback to the database and/or send it in email
            }
            return View();
        }

Create a view for ‘Suggest’, it doesn’t matter what’s in it as we don’t use the result currently.

And, finally we need a bit of CSS for the feedback icon itself:

/* Feedback tab */
#feedbackTab
{
	right:0;
    position:fixed;
    width:32px;
    height:150px;
    top: 150px;
    z-index:1;
}

The feedback button now floats on every page, 150px from the top and it’s glued to the right hand side.

Of course you’ll need your own feedback image, or feel free to borrow the one here:- http://www.signswift.com/images/feedback.png

So with that all in place, click the feedback button and a form like this should appear. Fill the information in and send it to the server. Note how we silently grab the url of the page too so we can see which page they were on when the submitted the feedback.

Feedback Form

A simple web crawler in C# using HtmlAgilityPack

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.Net;

namespace LinkChecker.WebSpider
{
    /// <summary>
    /// A result encapsulating the Url and the HtmlDocument
    /// </summary>
    public abstract class WebPage
    {
        public Uri Url { get; set; }

        /// <summary>
        /// Get every WebPage.Internal on a web site (or part of a web site) visiting all internal links just once
        /// plus every external page (or other Url) linked to the web site as a WebPage.External
        /// </summary>
        /// <remarks>
        /// Use .OfType WebPage.Internal to get just the internal ones if that's what you want
        /// </remarks>
        public static IEnumerable<WebPage> GetAllPagesUnder(Uri urlRoot)
        {
            var queue = new Queue<Uri>();
            var allSiteUrls = new HashSet<Uri>();

            queue.Enqueue(urlRoot);
            allSiteUrls.Add(urlRoot);

            while (queue.Count > 0)
            {
                Uri url = queue.Dequeue();

                HttpWebRequest oReq = (HttpWebRequest)WebRequest.Create(url);
                oReq.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";

                HttpWebResponse resp = (HttpWebResponse)oReq.GetResponse();

                WebPage result;

                if (resp.ContentType.StartsWith("text/html", StringComparison.InvariantCultureIgnoreCase))
                {
                    HtmlDocument doc = new HtmlDocument();
                    try
                    {
                        var resultStream = resp.GetResponseStream();
                        doc.Load(resultStream); // The HtmlAgilityPack
                        result = new Internal() { Url = url, HtmlDocument = doc };
                    }
                    catch (System.Net.WebException ex)
                    {
                        result = new WebPage.Error() { Url = url, Exception = ex };
                    }
                    catch (Exception ex)
                    {
                        ex.Data.Add("Url", url);    // Annotate the exception with the Url
                        throw;
                    }

                    // Success, hand off the page
                    yield return new WebPage.Internal() { Url = url, HtmlDocument = doc };

                    // And and now queue up all the links on this page
                    foreach (HtmlNode link in doc.DocumentNode.SelectNodes(@"//a[@href]"))
                    {
                        HtmlAttribute att = link.Attributes["href"];
                        if (att == null) continue;
                        string href = att.Value;
                        if (href.StartsWith("javascript", StringComparison.InvariantCultureIgnoreCase)) continue;      // ignore javascript on buttons using a tags

                        Uri urlNext = new Uri(href, UriKind.RelativeOrAbsolute);

                        // Make it absolute if it's relative
                        if (!urlNext.IsAbsoluteUri)
                        {
                            urlNext = new Uri(urlRoot, urlNext);
                        }

                        if (!allSiteUrls.Contains(urlNext))
                        {
                            allSiteUrls.Add(urlNext);               // keep track of every page we've handed off

                            if (urlRoot.IsBaseOf(urlNext))
                            {
                                queue.Enqueue(urlNext);
                            }
                            else
                            {
                                yield return new WebPage.External() { Url = urlNext };
                            }
                        }
                    }
                }
            }
        }

        ///// <summary>
        ///// In the future might provide all the images too??
        ///// </summary>
        //public class Image : WebPage
        //{
        //}

        /// <summary>
        /// Error loading page
        /// </summary>
        public class Error : WebPage
        {
            public int HttpResult { get; set; }
            public Exception Exception { get; set; }
        }

        /// <summary>
        /// External page - not followed
        /// </summary>
        /// <remarks>
        /// No body - go load it yourself
        /// </remarks>
        public class External : WebPage
        {
        }

        /// <summary>
        /// Internal page
        /// </summary>
        public class Internal : WebPage
        {
            /// <summary>
            /// For internal pages we load the document for you
            /// </summary>
            public virtual HtmlDocument HtmlDocument { get; internal set; }
        }
    }
}

Using Exception.Data to add additional information to an Exception

Introduction

Whether you are writing a WinForms application or a complex .NET web site, you will invariably be catching exceptions, logging them and reporting them somewhere. (In this post, I’m not going to explain how to log exceptions). Simply reporting the exception as-thrown rarely captures enough information to be able to diagnose what happened. A FileNotFoundException for instance isn’t much use unless you know which file it was.

One way to deal with this issue is to wrap an exception up in a more explicit exception that includes the extra information, e.g.

string filename ...
try
{
   //... do something with the file
}
catch (FileNotFoundException ex)
{
   CustomException ex2 = new CustomException("Missing cache: " + filename", ex);
   throw ex2;
}

This approach works but it leads to a lot of custom exceptions that are just extra work to create and maintain.  Sometimes you’ll want a custom exception because you are going to handle it in a different way in some outer scope, but often you just want to log the error and redirect the user to an error page as there is nothing else you can do to fix the problem.

In cases like this, you can simplify things greatly by using the little-known .data property on an Exception. This is an IDictionary for a “collection of key/value pairs that provide additional user-defined information about the exception” [MSDN].

Using this approach, you can write:

try
{
   ...
}
catch (FileNotFoundException ex)
{
   ex.Data.Add("cache filename", filename);
   throw;
}

Each surrounding scope can include a similar Try-Catch that adds more information to .Data so by the time you get to the top-most scope you have added a complete picture as to what might have caused the exception.  And in doing so you haven’t lost any of the StackTrace information, nor have you wrapped the exception up needlessly in another exception.

At a higher level in your Global.asax file where you catch all unhandled exceptions, you can add even more to the .Data collection and perhaps include all the interesting parameters on HttpContext like RawUrl, cookies, …


ex.Data.Add("RawUrl", request.RawUrl);
try
{
   foreach (string cookieName in request.Cookies)
   {
      try
      {
         HttpCookie cookie = request.Cookies[cookieName];
         string key = "Cookie " + cookie.Path + " " + cookieName;
         if (!ex.Data.Contains(key))
         {
             ex.Data.Add(key, cookie.Value.ToString());
         }
      }
      catch
      {
         // deliberately nothing in here, should
         // never happen, just being cautious
      }
   }
   // An extension method I use to spot bots - write your own ...
   if (request.IsABot())
   {
      ex.Data.Add("BOT", "************* BOT *****************");
   }
   ex.Data.Add("UserAgent", request.UserAgent);
   ex.Data.Add("Referrer", request.UrlReferrer);
   ex.Data.Add("User Host", request.UserHostName);
}
catch
{
   // deliberately nothing in here, should
   // never happen, just being cautious
   // but we definitely don't want to cause
   // an exception while handling one!
}

Exception Reporting Code

Now in your exception reporting code, you can write out the exception message and stack trace followed by a dump of all the key value pairs in .Data. I tend to use log4net on each server writing to a rolling log file and SQL server to capture the exception data centrally. For SQL, you’ll probably want one table for the Exception itself and another table with a row for each key/value pair in .Data.

Comments

One cause of Exceptions on web servers is bots and client-side ‘web accelerators’.  Both of these can hit pages with incorrect or outdated parameters that you simply didn’t expect to receive. That’s why I add a BOT warning on every exception as the exception itself may seem severe but in reality it’s benign and no user has ever seen it.  I even found one antivirus product that takes each request you make and sends the URL to Japan where another server makes a second request back to check the page for viruses! It even pretends not to be a Bot in the UserAgent and of course, all your ‘security- through-obscurity’ URLs are now sitting on a server in Japan, but you know security through obscurity is no security at all, right?

Another browser add on called FunWebProducts would routinely corrupt Viewstate information so if you see that in your exceptions log, you know who to blame.

A strongly-typed natural language engine (C# NLP)

Here is an explanation of the natural language engine that powers my home automation system. It’s a strongly-typed natural language engine with tokens and sentences being defined in code. It currently understands sentences to control lights, heating, music, sprinklers, … You can ask it who called, you can tell it to play music in a particular room, … it tells you when a car comes down the drive, when the traffic is bad on I-90, when there’s fresh snow in the mountains, when it finds new podcasts from NPR, … and much more.

The natural language engine itself is a separate component that I hope one day to use in other applications.

Existing Natural Language Engines

  • Have a large, STATIC dictionary data file
  • Can parse complex sentence structure
  • Hand back a tree of tokens (strings)
  • Don’t handle conversations

C# NLP Engine

  • Defines strongly-typed tokens in code
  • Uses type inheritance to model ‘is a’
  • Defines sentences in code
  • Rules engine executes sentences
  • Understands context (conversation history)

Sample conversation

Goals

  • Make it easy to define tokens and sentences (not XML)
  • Safe, compile-time checked definition of the syntax and grammar (not XML)
  • Model real-world inheritance with C# class inheritance:
  • ‘a labrador’ is ‘a dog’ is ‘an animal’ is ‘a thing’
  • Handle ambiguity, e.g.
play something in the air tonight in the kitchen
remind me at 4pm to call john at 5pm

C# NLP Engine Structure

Tokens – Token Definition

  • A hierarchy of Token-derived classes
  • Uses inheritance, e.g. TokenOn is a TokenOnOff is a TokenState is a Token. This allows a single sentence rule to handle multiple cases, e.g. On and Off
  • Derived from base Token class
  • Simple tokens are a set of words, e.g. « is | are »
  • Complex tokens have a parser, e.g. TokenDouble

A Simple Token Definition

public class TokenPersonalPronoun : TokenGenericNoun
{
   internal static string wordz { get { return "he,him,she,her,them"; } }
}
  • Recognizes any of the words specified
  • Can use inheritance (as in this example)

A Complex Token

public abstract class TokenNumber : Token
{
  public static IEnumerable<TokenResult> Initialize(string input)
  {
  …
  • Initialize method parses input and returns one or more possible parses.

TokenNumber is a good example:

  • Parses any numeric value and returns one or more of TokenInt, TokenLong, TokenIntOrdinal, TokenDouble, or TokenPercentage results.

The catch-all TokenPhrase

public class TokenPhrase : Token

TokenPhrase matches anything, especially anything in quote marks

   e.g. add a reminder "call Bruno at 4pm"

The sentence signature to recognize this could be

(…, TokenAdd, TokenReminder, TokenPhrase, TokenExactTime)

This would match the rule too …

add a reminder discuss 6pm conference call with Bruno at 4pm

TemporalTokens

A complete set of tokens and related classes for representing time

  • Point in time, e.g. today at 5pm
  • Approximate time, e.g. who called at 5pm today
  • Finite sequence, e.g. every Thursday in May 2009
  • Infinite sequence, e.g. every Thursday
  • Ambiguous time with context, e.g. remind me on Tuesday (context means it is next Tuesday)
  • Null time
  • Unknowable/incomprehensible time

TemporalTokens (Cont.)

Code to merge any sequence of temporal tokens to the smallest canonical representation,

e.g.

the first thursday in may 2009

->
{TIMETHEFIRST the first} + {THURSDAY thursday} + {MAY in may} + {INT 2009 -> 2009}

->
[TEMPORALSETFINITESINGLEINTERVAL [Thursday 5/7/2009] ]

TemporalTokens (Cont.)

Finite TemporalClasses provide

  • A way to enumerate the DateTimeRanges they cover
  • All TemporalClasses provide

  • A LINQ expression generator and Entity-SQL expression generator allowing them to be used to query a database
  • Existing Token Types

    • Numbers (double, long, int, percentage, phone, temperature)
    • File names, Directories
    • URLs, Domain names
    • Names, Companies, Addresses
    • Rooms, Lights, Sensors, Sprinklers, …
    • States (On, Off, Dim, Bright, Loud, Quiet, …)
    • Units of Time, Weight, Distance
    • Songs, albums, artists, genres, tags
    • Temporal expressions
    • Commands, verbs, nouns, pronouns, …

    Rules – A simple rule

       /// &lt;summary&gt;
       /// Set a light to a given state
       /// &lt;/summary&gt;
       private static void LightState(NLPState st, TokenLight tlight, TokenStateOnOff ts)
       {
          if (ts.IsTrueState == true) tlight.ForceOn(st.Actor);
          if (ts.IsTrueState == false) tlight.ForceOff(st.Actor);
          st.Say("I turned it " + ts.LowerCased);
       }
    

    Any method matching this signature is a sentence rule:-  NLPState, Token*

    Rule matching respects inheritance, and variable repeats … (NLPState st, TokenThing tt, TokenState tokenState, TokenTimeConstraint[] constraints)

    Rules are discovered on startup using Reflection and an efficient parse graph is built allowing rapid detection and rejection of incoming sentences.

    State – NLPState

    • Every sentence method takes an NLPState first parameter
    • State includes RememberedObject(s) allowing sentences to react to anything that happened earlier in a conversation
    • Non-interactive uses can pass a dummy state
    • State can be per-user or per-conversation for non-realtime conversations like email
      • Chat (e.g Jabber/Gtalk)
      • Web chat
      • Email
      • Calendar (do X at time Y)
      • Rich client application
      • Strongly-typed natural language engine
      • Compile time checking, inheritance, …
      • Define tokens and sentences (rules) in C#
      • Strongly-typed tokens: numbers, percentages, times, dates, file names, urls, people, business objects, …
      • Builds an efficient parse graph
      • Tracks conversation history
    • User Interface

      Works with a variety of user interfaces

      Summary

      Future plans

      Expanded corpus of knowledge

    • Company names, locations, documents, …
    • Generate iCal/Gdata Recurrence

    • From TimeExpressions

    Interesting or useful links on Twitter this week relating to .NET and C#

    Here are some of the more interesting and useful links I found on Twitter this week:
    Strongly typed route construction :- http://www.assembla.com/wiki/show/snooze
    Amazon’s Dynamo – high availability key-value store : http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf
    An awesome domain name finding tool :- http://www.nxdom.com/

    String extension methods for truncating and adding ellipsis

    Some useful extension methods for working with strings and IEnumerable<string>.  These come in handy when logging as you often want to show just 80 characters (say) in a log entry.

    /// <summary>

    /// Substring but OK if shorter

    /// </summary>

    public static string Limit(this string str, int characterCount)

    {

    if (str.Length <= characterCount) return str;

    else return str.Substring(0, characterCount).TrimEnd(‘ ‘);

    }

    /// <summary>

    /// Substring with elipses but OK if shorter, will take 3 characters off character count if necessary

    /// </summary>

    public static string LimitWithElipses(this string str, int characterCount)

    {

    if (characterCount < 5) return str.Limit(characterCount);       // Can’t do much with such a short limit

    if (str.Length <= characterCount – 3) return str;

    else return str.Substring(0, characterCount – 3) + “…”;

    }

    /// <summary>

    /// Substring with elipses but OK if shorter, will take 3 characters off character count if necessary

    /// tries to land on a space.

    /// </summary>

    public static string LimitWithElipsesOnWordBoundary(this string str, int characterCount)

    {

    if (characterCount < 5) return str.Limit(characterCount);       // Can’t do much with such a short limit

    if (str.Length <= characterCount – 3)

    return str;

    else

    {

    int lastspace = str.Substring(0, characterCount – 3).LastIndexOf(‘ ‘);

    if (lastspace > 0 && lastspace > characterCount – 10)

    {

    return str.Substring(0, lastspace) + “…”;

    }

    else

    {

    // No suitable space was found

    return str.Substring(0, characterCount – 3) + “…”;

    }

    }

    }

    The Blog of Ian Mercer: Home Automation++

    This is the blog of Ian Mercer, Serial entrepreneur, Digital Mapping Pioneer, Inventor of Windows Movie Maker, Microsoft Producer, HighMat, SnapTune, … Patent holder, Guinness world record holder, and founder and CEO of SignSwift, LLC,

    Here you’ll find my thoughts on Home automation, Energy Conservation, Programming, Operations, Entrepreneurship, Business, Startups, Quality, Agile, Optimization, .NET, Natural Language Processing, Digital Signage and more.

    Home Automation Energy SavingMy home automation system recently won 1st and 3rd place in the international, Microsoft MyDotNetStory competition.  You can view a demonstration of it under the home automation menu above.  I believe that it is the world’s smartest house because I haven’t seen anything smarter.  It controls lights, heating, sprinklers, audio, and more; it has hundreds of sensors including PIR, strain gauges, door switches, and more; it interfaces to Caller ID, PBX, Google Calendar, Google Contacts, Email, NOAA, Twitter, Facebook, RSS, Traffic, Podcasts and more. For the most part it works autonomously doing the right thing and reducing our energy consumption by over 40%.  You can control it using a web, voice or chat interface.  It has a unique Natural Language Interface that understands sentences and can hold a two-way conversation with you.

    Keyword diagram snippetUnder the SEO menu you’ll find my SEO keyword mapping tool; it can untangle a list of keyword phrases and volumes (like you get from Google’s Adwords tools) to give you a clearer picture of the keywords you need to put on your pages.  Using variable sized boxes and lines it shows you which words are the most important and how they are linked.

    Thoughts under programming are mostly related to Microsoft’s .NET platform and the C# language but there are some that are more general in nature.  I’ve been using Visual Studio 2010 and .NET 4 extensively recently including the Entity Framework, WCF, WPF and Silverlight.

    You can view my professional profile on Linkedin or follow me on Twitter.

    I’m also an avid photographer and videographer and I’m in the process of adding a few of my favorite pictures to the site.