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 Sep 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 Sep 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 Sep 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.

10 Aug 2011

Unable to use SQL Server because ASP.NET version 2.0 Session State is not installed

Setting up a new MVC 3 (ASP.NET 4) site, using SQL Session State. Got the message:

Unable to use SQL Server because ASP.NET version 2.0 Session State is not installed on the SQL server

But I *had* set up Session State, so this was perplexing.

Turns out this was because I had only given the ASP.NET user db_datareader and db_datawriter permissions on the Session State database. Those permissions don't allow the user to EXEC sprocs. I gave the user db_owner perms and all was well.

Stupid unhelpful error message!

Linq select vs Enumerable.Select()

I found the MSDN docs a bit confusing with this, so here's a brief aide memoire about how to transform a list of one Type to a list of another, using Linq and also Enumerable Linq methods.

In this case I'm transforming from a List of EF Entities (called promotions here) to a list of MVC SelectListItems.

Standard Linq stylee

var query = from promo in promotions
select new SelectListItem { Text = promo.Name, Value = promo.Id.ToString() };

Enumerable Linq Method stylee


var query = promotions.Select(promo => new SelectListItem() { Text = promo.Name, Value = promo.Id.ToString() });

To get a List out, you just do query.ToList().

13 Jul 2011

Load-Balanced IIS 7.5 Web Server ASP.NET SQL Session State problem

We had a problem recently with an ASP.NET website where the users' sessions were behaving oddly - session data appearing, disappearing and re-appearing.

As the site is hosted on two webservers using network load-balancing, I figured the problem must have something to do with that, but I was puzzled because I thought my configuration's use of a single, central, standard ASP.NET SQL Session State database would remove such problems.

Well, apparently this is only true if IIS is set up correctly and consistently on all your webserver machines. You see, if you check the AspStateTempApplications table in the AspState database, you'll see reference to website Instance IDs (e.g. /W3SVC/1/Root, /W3SVC/2/Root etc). So, ASP.NET hooks up your browser's session cookie to your session data using the Instance ID of the website serving you.

But what if the load-balanced servers host several sites, and due to the order of setup, your site on one server has a different Instance ID to the one on the other? That's right, you end up getting served up with different session data depending which server the load-balancer allocates to your HTTP request.

So, how to fix the prob? You just need to get the IIS Instance IDs in sync on the 2 servers. For IIS 6 there's a script you can run.

For IIS 7.5 however, you can't use adsutil.vbs style solutions anymore. However that's because the Metabase is old-hat and we rock config files now baby! You can set the id of a site using its id attribute found in C:\Windows\System32\inetsrv\config\applicationHost.config. You need admin privs to edit that, and need to restart IIS afterwards.

Easier still,

1. Remote Desktop onto server 1, open IIS Mgr, click on the problem Site and choose Advanced Settings in the sidebar.
2. Change the ID to something unique e.g. 10. Click OK.
3. Restart the web service (c:\windows\system32\iisreset /restart)

Do the same for server 2 (ensure the Site ID is the same as on server 1).

Again, restart the website after the change for it to take effect.

28 Jun 2011

Settings.settings vs web.config file with a web service reference

I have a class library called myClassLibrary that contains a reference to a web service.
The web service URL is stored in a Settings.settings file.
This in turn creates an app.config file.

I use myClassLibrary in a web project, and I ran into the problem that the default URL for the web service that I had specified in Settings.settings needed to be different when my web project was in our test environment. So I wanted to be able to override the Settings.settings value with, say, a value in my web.config.

This is how you do it:

Settings.settings


The URL is defined as a value with Scope set to "Application" and a GenerateDefaultValueInCode property set to "TRUE".
This provides a default value when myClassLibrary is run in a non-web context with no override in the app.config file.

app.config


The URL is set in an applicationSettings block to override the default value when the class library is used in a non-web context.

    <applicationSettings>
        <myClassLibrary.Settings>
            <setting name="myWebServiceUrl" serializeAs="String">
                <value>http://whatever.com/myService</value>
            </setting>
        </myClassLibrary.Settings1>
    </applicationSettings>

web.config


Here is where we do the override for use of the class library in a web context.

Firstly we have to define a configuration block that will match the one in app.config:

  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup" >
      <section name="myClassLibrary.Settings" type="System.Configuration.ClientSettingsSection" />
    </sectionGroup>    
  </configSections>

Then we just implement that block with our override value.

  <applicationSettings>
    <myClassLibrary.Settings>
      <setting name="myWebServiceUrl" serializeAs="String">
        <value>http://another.com/myAlternativeService</value>
      </setting>
    </myClassLibrary.Settings>
  </applicationSettings>  

22 Jun 2011

.NET Project File - Include External CommonAssemblyInfo file

I wanted to register a common AssemblyInfo.cs file in the Properties folder of my project. This file is actually external to my project, so how to do it?

Add this to your csproj file in the <ItemGroup> section with the Compile elements.

<Compile Include="..\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>

Then just strip out the [assembly: Whatever()] bits from the original AssemblyInfo.cs file and put them in the CommonAssemblyInfo.cs file.

5 May 2011

.Net DateTime with TimeZones , UTC, DST problems

Doing DateTime work with different TimeZones? Having a pain converting to UTC, dealing with Daylight Saving Time (DST) etc?

Check the TimeZoneInfo class in .Net 3.5 +.

8 Apr 2011

Localization of jQuery UI DatePicker with ASP.NET

Hello folks! Do you want to make your jQuery DatePicker play nicely with your ASP.NET localization settings?

When you set up your DatePicker inputs on the page, try this:


$('.DatePicker').datepicker({
dayNamesMin: ['<%= string.Join("', '", System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortestDayNames) %>'],
monthNames: ['<%= string.Join("', '", System.Globalization.DateTimeFormatInfo.CurrentInfo.MonthNames) %>'],
monthNamesShort: ['<%= string.Join("', '", System.Globalization.DateTimeFormatInfo.CurrentInfo.AbbreviatedMonthNames) %>']
});

6 Apr 2011

DevExpress ASP.NET Chart : Trial message problem

Well this was annoying and wasted half a day!

We have a registered copy of DevExpress which we use on a site for charting.
We deployed our ASP.NET site to the live server.
We deployed the registered DevExpress DLLs to the site bin folder.
(Find them in C:\Program Files (x86)\DevExpress 2010.1\Components\Sources\DevExpress.DLL - Don't copy the *.design.dll files though)

The web chart pages worked but displayed a message about using the TRIAL version of DevExpress.

Turns out that VS2010 was creating a licenses.licx file in the root of the project which was screwing it up. Annoyingly, the licx file didn't show in the Solution Explorer until you click the little "Show All Files" icon.

Solution: We had to delete the licenses.licx file, then rebuild the project, then redeploy.

More info: http://community.devexpress.com/blogs/ctodx/archive/2009/03/06/licenses-licx-file-woes.aspx

18 Feb 2011

Free Reflector Alternative

RedGate! Bah, and humbug. Their DB products have often come in useful for me, but they are also pretty slow and I can't help thinking that they could be a lot better. But now they've riled me! Raaargh!

Reflector's forced-update feature was a bit annoying even back in the days of Lutz Roeder, but at least there was a fair idea behind it - to ensure everyone had the latest and greatest free version. Now they've revealed that the forced update from the free V6 version is going to install the paid-for V7 version with an evaluation period before lock-down.

Well, this sucks. Why can't they release a final free V6 version with no forced update? Oh yeah, $$$.

Good job SharpDevelop have released their own free alternative to Reflector. I've had a play and even in Beta it does everything I need. So wooyay to them!
If I helped you out today, you can buy me a beer below. Cheers!