18 Jan 2012

ValueInjecter - matching nullable to non-nullable values

Here's a little ValueInjecter plugin I wrote to handle ValueInjecter matching for properties where the name matches but one is nullable and the other is not.
        
public class NullableInjection : ConventionInjection
{
 protected override bool Match(ConventionInfo c)
 {
  return c.SourceProp.Name == c.TargetProp.Name &&
      (c.SourceProp.Type == c.TargetProp.Type 
    || c.SourceProp.Type == Nullable.GetUnderlyingType(c.TargetProp.Type)
    || (Nullable.GetUnderlyingType(c.SourceProp.Type) == c.TargetProp.Type 
      && c.SourceProp.Value != null )
    );
 }

 protected override object SetValue(ConventionInfo c)
 {
  return c.SourceProp.Value;
 }
}

So I just use it like so:
targetModel.InjectFrom<NullableInjection>(sourceModel);

14 Dec 2011

Visual Studio 2010 (VS2010) Javascript Function Folding - Code Region Outlining

I thought to myself, as I swam through an ASP.NET Razor View crammed with Javascript functions, 'SURELY someone has made a VS plugin that does function code folding?'.

Yup, Microsoft has. http://visualstudiogallery.msdn.microsoft.com/872d27ee-38c7-4a97-98dc-0d8a431cc2ed

9 Dec 2011

Visual Studio RegEx Regular Expression Cheat Sheet

Why MS decided to use a non-standard RegEx parser for Visual Studio 2010's Find/Replace controls, I don't know. All I do know is that I forget the syntax EVERY FRIGGING TIME in the heat of battle. So, here's the skinny:

Match group definition using CURLY BRACE {}
Match group replacement using BACKSLASH \

So to turn <bob.holness> to *bob* use:

FIND: \<{:a#}\>
REPLACE: *\1*

NOTE:

The :a is the VS alpha-numeric character match pattern
The # is the VS 'non-greedy' 1-or-more match pattern

BREAKING NEWS: Microsoft have come to their senses with VS2012 and use the standard .NET RegEx parser in the Find/Replace box now. Phew.





15 Nov 2011

IE8 window.location HTTP_REFERER

Stupid HTTP variable, HTTP_REFERER. It's spelt wrong for a start.

Anyway, to cut a long, stupid story short, an HTTP call invoked from a javascript window.location change will usually set the HTTP_REFERER variable on IIS because the browser sends a Referer header.

I say 'usually' because it DOESN'T FRIGGING WORK in IE8. IE9, FF, Chrome, fine. IE8, nope.

Sigh.


9 Nov 2011

Rockalldll.dll missing / not found error - Rockall Heap Manager on Windows 7

This week's mystery was a recurring error message in Windows 7 about a missing DLL - RockallDll.dll.

It sounded dodgy, and a quick google returned about a million nasty DLL sites purporting to offer a nice shiny replacement DLL, no doubt festooned with viruses and trojans.

So I didn't do that. I had to do some pretty deep searching to find out that this DLL was originally installed as part of Hermann Schinagl's Link Shell Extension that I installed ages ago. For some reason I had installed it on my E drive. Well, I don't know why it had stopped working, but I uninstalled it, downloaded the latest version and installed it on C drive instead.

Problem solved, woohoo. And I do recommend LSE as a quick way of creating symbolic links in Windows.


3 Nov 2011

IntelliType Pro 8, Media Keys and iTunes 10.5

I just got me a new MS Sidewinder X4 keyboard, and very swanky it is too. However, it requires Microsoft IntelliType Pro to work, and after installing that, I was annoyed to find that the Media Keys (Play, Pause, Prev Track, Next Track) didn't work with iTunes.

Here's what I found out.
  • iTunes control worked fine if I uninstalled IntelliType Pro, but this was no good because then I lost the use of the keyboard's Macro keys.
  • By doing the trick of launching iTunes as administrator (right click on the iTunes icon - choose "Run as administrator") , iTunes can be controlled from the Media keys - But ONLY when iTunes is in Window Focus. 
  • Launching the IntelliType process (itype.exe) as administrator makes no difference.
However I have found a Heath Robinson / Rube Goldberg stylee solution! 

HKTunes Portable is free software that launches iTunes for you and attaches custom key handlers to the Play/Pause, Next/Previous controls. So I configured that to use some wild, unlikely key combos, and then I set up those same key combos as Macros for the Media Keys in IntelliType Pro (Start > Microsoft Keyboard > Key Settings).

The only drawback is that you have to remember to launch HKTunes rather than iTunes, but I just replaced the pinned launcher in my task bar so it's not a problem. Wish Microsoft would sort out the underlying prob though!

UPDATE


I found a better solution! Check this guy's EXCELLENT MediaKeys app!

UPDATE UPDATE 23 April 2012

Looks like this is fixed as of Intellitype 8.2 (wasn't listed as Intellitype Pro for some reason?) and iTunes 10.6. GOOD.

30 Oct 2011

Keyboard Test utility for Windows 7

I have a duff keyboard, but I only proved it was duff by using a little utility to test it. Unfortunately, finding a Key Press Test application for windows 7 was right nightmare!

So I wrote one. Enjoy: Keyboard Tester.

26 Sept 2011

jQuery Post a javascript array to ASP.NET MVC

I wanted to post a bunch of ID numbers to my MVC controller, which is sat waiting with the following signature:

public ActionResult UnParkLeads(IList<int> leadIds)


However, this post needed to be generated from jQuery - specifically we're sending through the data ids of entities that correspond to "checked" checkboxes in a list. So what we need was a way of iterating through the list of checked checkboxes, getting the IDs into an array, and sending that through ajax to the server, to be picked up with the correct signature action.

var leadIds = $('input.chkTileSelector:checked').map(function () {
                                                            return { name: 'leadIds', value: $(this).parents('div.Lead').data('id') };
                                                }).get();

$.ajax({
    url: '@Url.Action("UnParkLeads", "Lead")',
    type: 'POST',
    dataType: 'json',
    data: leadIds,
    success: function (result) {
        ReloadResultGrid();
    }
});    

The tricky bit was basically the construction of the javascript object literal in the map function: jQuery converts that array into the ajax querystring using its param() function, which requires name and value properties.

The result is that jQuery posts multiple values with the same name ('leadIds'), and MVC recognises that and converts them into an IList<int>.

8 Sept 2011

Using OutputCache with PartialView in MVC 3, with programmatic invalidation usingVaryByCustom too!

I've had a fun morning trying to cache partial views inside a dynamic page with MVC 3. Specifically, a partial view in a razor layout page (i.e. masterpage) that shows some dynamically generated data which I would like to hold off from regenerating for 60 seconds or so, even if the user refreshes or navigates around the site.

So I create my partial view like this - here we generate the time to show when the view is being cached

MyPartial.cshtml

Timestamp: @DateTime.Now.ToLongTimeString()

Then I create the controller action:

HomeController.cs

[OutputCache(Duration = 60)]
public ActionResult MyPartial()
{
    return PartialView();
}

Then I amend my layout page to include the call to the PartialView:

MyMaster.cshtml

Some header stuff
...
@Html.Action("MyPartial", "Home")
...
Some footer stuff

Well, that's all there is to it. The pitfalls I faced revolved around accidentally calling Html.Partial() from the layout page, which didn't work because it bypasses the controller attributes (i.e. it misses the OutputCache directive).

HOWEVER

Then I started wanting to reset the output cache when the underlying data changed, or when some user setting changed. So I knocked up this little solution using the OutputCache attribute's VaryByCustom property.

First a modification to the controller:

HomeController.cs

[OutputCache(Duration = 60, VaryByCustom = "WebApp.OutputCacheKey")]
public ActionResult MyPartial()
{
    return PartialView();
}

Every time OutputCache is called, it will check to see if that string has changed since last time. If it has changed, it invalidates the cache. "But it's a static string! How can it change?" I hear you cry. Yup, here's some voodoo magic. You can override a special method in global.asax that intercepts the call and returns ANOTHER string, wooo!

global.asax

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "WebApp.OutputCacheKey")
    {
        return WebApp.OutputCacheKey;
    }
    else
    {
        return base.GetVaryByCustomString(context, arg);
    }
}

Now, we need to implement this WebApp thing. It's just an approach I like to have a static class knocking around my web application that allows me to access stuff from one central place, like strongly-typed accessors for session variables, or my per-request EF datacontext. But for these purposes it would just look like this:

WebApp.cs

public static class WebApp
{
    internal static string OutputCacheKey
    {
        get
        {
            if (HttpContext.Current.Session["WebApp.OutputCacheKey"] == null)
            {
                ResetOutputCache();
            }
            return HttpContext.Current.Session["WebApp.OutputCacheKey"].ToString();
        }
    }

    internal static void ResetOutputCache()
    {
        HttpContext.Current.Session["WebApp.OutputCacheKey"] = Guid.NewGuid().ToString();
    }    
}

So, what we have now is an easy way to programatically tell the OutputCache to clear itself, with a simple call from anywhere in your controller code:

WebApp.ResetOutputCache();

Simples!

2 Sept 2011

MVC 3 DropDownListFor not selecting an item (Title property of model)

Have you got a problem with MVC 3 where your model has a property that is definitely set, but when you use it in a DropDownListFor, the value doesn't get selected from your SelectList? Me too, and I've solved it.

I had a viewmodel like so:

[Required]
public string Title { get; set; }

public List<SelectListItem> TitleSelectList
{
 get
 {
  var selectList = new List<SelectListItem>();
  selectList.AddRange(new string[] { "Mr", "Mrs", "Miss", "Ms", "Dr", "Other" }.Select(item => new SelectListItem() { Text = item, Value = item }));
  selectList.Insert(0, new SelectListItem { Text = "Choose...", Value = "" });
  return selectList;
 }
}

and in my View, I was showing it like this:

@Html.DropDownListFor(model => model.Title, Model.TitleSelectList)

HOWEVER, in my View, I also had this lurking:

@{
    ViewBag.Title = "My Lovely Page";
}

Yup, with DropDownListFor at least, ViewBag properties are used in preference to model properties when MVC tries to find the selected value. It couldn't find "My Lovely Page" in the SelectList, and so nothing was selected. When I changed my ViewBag property to ViewBag.PageTitle instead, everything started working properly.
If I helped you out today, you can buy me a beer below. Cheers!