Tuesday, March 29, 2011

jQuery update for IE9

When Internet Explorer was released, I downloaded it immediately and replaced my IE8. It works superbly except on a project that I was working on. For some reason, some javascripts are causing errors and won't work. I was using jQuery 1.4.x and jQuery UI 1.8.1.

After some investigation, the existence of the meta-tag to force IE compatibility and the outdated jQuery scripts were causing all the errors.

So I removed the meta-tag ("<meta http-equiv="x-ua-compatible" content="IE=8" />") and updated the jQuery reference to the latest greatest (1.5.1 and UI 1.8.11) - and all are happy again.

-- read more and comment ...

Monday, March 7, 2011

Munchkin Strategy: Wizard

Munchkin is a card game, where you play a character in battling monsters in order to get to the winning level (level 10 for regular or 20 for EPIC). The game involves some luck (drawing cards), strategies, a good amount of persuasion, trash-talking, and bantering back-and-forth with other players. That combination makes the game a lot of fun, interactive, and can be played again and again without getting boring.

For more information about Munchkin, you can read their website: http://www.worldofmunchkin.com/

If you are familiar with Dungeons & Dragons, then Munchkin should be somewhat familiar to you - a funny version of D&D. It has races & classes, curses, combat strength, charms, potions, etc.

The rest of this post assumes that you are somewhat familiar with the game, basic rules, and its vocabularies - outlining a basic strategy to use if you are playing as a Wizard class.

-- read more and comment ...

Wednesday, March 2, 2011

Integrating ELMAH into your ASP.NET MVC project

What is ELMAH? ELMAH stands for Error Logging Modules and Handlers. So it does what it says, logging errors. It's a plug-able stand alone module that you can integrate with your project quite easily.

From ELMAH's site:
Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilities without changing a single line of your code:

  • Logging of nearly all unhandled exceptions.
  • A web page to remotely view the entire log of recoded exceptions.
  • A web page to remotely view the full details of any one logged exception.
  • In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
  • An e-mail notification of each error at the time it occurs.
  • An RSS feed of the last 15 errors from the log. 
Sounds awesome! Hell yes - beats writing your own any day! How do you integrate it with ASP.NET MVC project?

1. Download ELMAH
You can get the compiled assemblies or the source files here: http://code.google.com/p/elmah/

2. Reference ELMAH's assemblies
If you get the compiled assemblies, just make a reference to Elmah.dll. If you get the source, you will need to build it and then reference it (either by project or by binary).

3. Modify web.config
Open your web.config and make these changes:
a. Add this "configSections" within "configuration"
<configSections>
        <sectionGroup name="elmah">
            <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
            <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/>
            <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah"/>
            <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
        </sectionGroup>
    </configSections>
b. Add this "elmah" section within "configuration" under the "configSections". This will enable ELMAH to save the error log to the database using "MyAppConnectionString" connection string. If you want to save the log into XML files on a local disk, you can uncomment the second line (and comment the 4th line) and specify the saving location under "logPath".
<elmah>
        <!--<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data"/>-->
        <security allowRemoteAccess="1"/>
        <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="MyAppConnectionString"/>
    </elmah>
c. Within "system.web" section, add these lines:
<httpHandlers>
            <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
        </httpHandlers>
        <httpModules>
            <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
        </httpModules>
d. Within "configuration", configure the permission to see the log. Basically it will deny all users unless users are logged in and user name is listed in the "allow" list. Enable that by adding these lines:
<location path="elmah.axd">
        <system.web>
            <authorization>
                <allow users="admin,joe,bob"/>
                <deny users="*"/>
            </authorization>
        </system.web>
    </location>

4. Modify global.asax
Check in your global.asax whether this line exists:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
If it is, then no more changes are needed in the global.asax.

5. Preparing Database
If you elect to store the log in the database, then some tables and stored procedures must be created before ELMAH can be functional. Get the script to create all those tables & stored procedures here: http://code.google.com/p/elmah/wiki/Downloads?tm=2 and run it.

That should be it and ELMAH is ready to run - you can start accessing ELMAH under /elmah.axd from your root url.

But I went a step further - I want all exception, including handled one to also be captured in ELMAH. ASP.NET MVC provides an filter-attribute called "HandleError" to handle/catch all errors/exceptions happening in the controller or bubble all the way to the controller. So instead of using that, I made my own HandleError attribute that will log to ELMAH - and replace the stock [HandleError] with my [ELMAHHandleError] attribute.

6. Create [ELMAHHandleError] for all my controllers.
I took this code from NerdDinner example that ASP.NET team provides in CodePlex.
public class ELMAHHandleErrorAttribute : HandleErrorAttribute {
        public override void OnException(ExceptionContext context) {
            base.OnException(context);

            var e = context.Exception;
            if (!context.ExceptionHandled   // if unhandled, will be logged anyhow
                    || RaiseErrorSignal(e)      // prefer signaling, if possible
                    || IsFiltered(context))     // filtered?
                return;

            LogException(e);
        }

        private static bool RaiseErrorSignal(Exception e) {
            var context = HttpContext.Current;
            if (context == null)
                return false;
            var signal = ErrorSignal.FromContext(context);
            if (signal == null)
                return false;
            signal.Raise(e, context);
            return true;
        }

        private static bool IsFiltered(ExceptionContext context) {
            var config = context.HttpContext.GetSection("elmah/errorFilter") as ErrorFilterConfiguration;

            if (config == null) return false;

            var testContext = new ErrorFilterModule.AssertionHelperContext(context.Exception, HttpContext.Current);

            return config.Assertion.Test(testContext);
        }

        private static void LogException(Exception e) {
            var context = HttpContext.Current;
            ErrorLog.GetDefault(context).Log(new Error(e, context));
        }
    }

That's it!

For further reading:

-- read more and comment ...