Of Code and Me

Somewhere to write down all the stuff I'm going to forget and then need

Getting Json.Net and Gson json libraries to play nicely with dates using ISO formatting January 28, 2011

Filed under: C#,Java,Web,WebServices — Rupert Bates @ 2:38 pm

I am working on something at the moment where I have a service written in .net which serves json created using the Json.Net library. This is then consumed by a client app written in Java which uses the Gson library to deserialize that json into Java classes. This was all working fine except for dates which caused parse errors in Gson.

The solution I am using is:

use ISO time format when serializing with Json.Net

    string json = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());    

When Deserializing with Gson set the date format as follows:

        GsonBuilder b = new GsonBuilder();
        b.setDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        Gson gson = b.create();
        gson.fromJson(json, MyObjectType.class);
 

Donut caching in asp.net mvc 2 with Html.Action April 8, 2010

Filed under: Asp.Net,C#,MVC,Uncategorized,Web — Rupert Bates @ 11:22 am

[Update – ok, so this officially doesn’t work, which sucks. I’m having a look at alternatives, but at the moment it looks like that is going to be reverting to MVC 1.0]

To do donut caching in Asp.Net Mvc 1.0 required quite a bit of hacking (or at least that was the only way I could get it to work), but with version 2 things get much better because of the addition of the Html.Action method.

As a quick recap, ‘donut caching’ is when you cache the whole of a web page except for small parts within it – the holes in the donut. A classic use for it is pages which have some personalised aspect like a logged in user name but are otherwise identical for all users.

To solve exactly this scenario I used the following code:

A child action called LoggedInUserInfo in my HomeController

        [ChildActionOnly]
        public ActionResult LoggedInUserInfo(HttpContextBase context)
        {
            return View(context);
        }

with a view of the same name:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<HttpContextBase>" %>
<%@ Import Namespace="KableDirect.Service" %>
<%@ Import Namespace="KableDirect.Web.FrontEnd.Models.Shared"%>

    <ul>
        <li>You are logged in as <%= Model.User.Identity.Name %> </li>

        <li><%=Html.ActionLink("My Profile", "Profile", "Account")%></li>

        <%if (Model.User.IsAdmin()){%>
        <li><a href="<%= RouteHelper.GetAdminUrl(Model)%>">Admin</a></li>
        <%}%>
        <li><%=Html.ActionLink("Logout", "Logoff", "Account")%></li>
    </ul>

I also have the following HtmlHelper method to make calling the asp.net WriteSubstitution() method easier:

    public delegate string MvcCacheCallback(HttpContextBase context);
    public static class CacheHelper
    {
        public static object Substitute(this HtmlHelper html, MvcCacheCallback cb)
        {
            html.ViewContext.HttpContext.Response.WriteSubstitution(c => cb(new HttpContextWrapper(c)));
            return null;
        }
    }

Now I can call my child action within my MasterPage using Html.Action as follows:

<%=  Html.Substitute(context => Html.Action("LoggedInUserInfo", "Home", new {context}).ToString()) %>

It is important that your action takes the context as a parameter or it will only be called once the first time the page is hit and then get cached along with everything else.
It is also important that you have a route in your route table that will catch the {controller}/{action} url pattern. See this post for more details.

Phill Haack now has a warning on his site about problems with donut caching in Asp.Net Mvc 2, but this has worked fine for me, I’ll update here if I find scenarios where this doesn’t work.

There is a good introduction to Html.Action here.

 

Great error message from Castle Windsor March 30, 2010

Filed under: C#,Coding — Rupert Bates @ 8:19 pm

This is a great exception from the Castle Windsor IOC container:

Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
Add '<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel" />' to the <httpModules> section on your web.config

It tells you exactly what you need to do to fix the problem. If only more developers took the time to throw such helpful exceptions!

Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
Add ‘<add name=”PerRequestLifestyle” type=”Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel” />’ to the <httpModules> section on your web.config

 

Format a string in RFC 2822 format for use with Http headers in c# March 17, 2010

Filed under: Asp.Net,C#,Coding,Web — Rupert Bates @ 11:45 am
var lastModified = AppStart.ToString("ddd, dd MMM yyyy hh:mm:ss ") + "GMT"; //note the hard coded GMT, there doesn't seem to be any other way to get this

Custom Date and Time Format Strings on MSDN
Standard Date and Time Format Strings on MSDN

 

Call an extension method on IEnumerable using reflection February 17, 2010

Filed under: C#,Coding — Rupert Bates @ 6:27 pm

I recently needed to invoke the Cast extension method on a List via reflection, and found it was a bit different to what I was used to
I tried:

var cast = typeof (List<string>).GetMethod("Cast");

but this returned null, then after a bit of digging around I realised that because Cast is an extension method, I needed to get it from the class it is defined in which is System.Linq.Enumerable. This code gets us the MethodInfo for Cast:

var cast = typeof (Enumerable).GetMethod("Cast");

Then because Cast is a generic method we need to provide it with the TResult type parameter as follows:

var constructedCast = cast.MakeGenericMethod(ListType);

Then we can invoke it:

var castVals = constructedCast.Invoke(null, new[]{ theList});

notice that the first parameter to Invoke is null because extension methods are static, and also that we pass in the List we want to invoke the method on, which then becomes the ‘this’ parameter of the extension method.

The result of Cast is a CastIterator and I wanted a List so I can then call ToList in the same way and I end up with a List cast to the type I am interested in.

//The result of Cast<TResult> is a a CastIterator so we need to call ToList on this
var toList = typeof (Enumerable).GetMethod("ToList");
var constructedToList = toList.MakeGenericMethod(ListType);
var castList = constructedToList.Invoke(null, new [] {castVals});
 

An extended Html.Encode function for the Asp.Net Mvc HtmlHelper February 12, 2010

Filed under: Asp.Net,C#,MVC — Rupert Bates @ 2:52 pm

The built in Asp.Net Html encoding function misses out a large number of extended characters (including apostrophes). This extension method for the HtmlHelper class does a much more thorough job:

using System.Collections.Generic;
using System.Web.Mvc;

namespace KableDirect.Web.FrontEnd.Helpers
{
    public static class HtmlHelperExtensions
    {
        #region The List of replacements

        public static readonly Dictionary<string, string> Replacements = new Dictionary<string, string>
                                                                             {
                                                                                 {"–", "&#8211;"},
                                                                                 {"—", "&#8212;"},
                                                                                 {"‘", "&#8216;"},
                                                                                 {"’", "&#8217;"},
                                                                                 {"‚", "&#8218;"},
                                                                                 {"“", "&#8220;"},
                                                                                 {"”", "&#8221;"},
                                                                                 {"„", "&#8222;"},
                                                                                 {"†", "&#8224;"},
                                                                                 {"‡", "&#8225;"},
                                                                                 {"•", "&#8226;"},
                                                                                 {"…", "&#8230;"},
                                                                                 {"‰", "&#8240;"},
                                                                                 {"€", "&#8364;"},
                                                                                 {"™", "&#8482;"},
                                                                                 {"'", "&#39;"},
                                                                                 {"ą", "&#261;"},
                                                                                 {"Ą", "&#260;"},
                                                                                 {"ę", "&#281;"},
                                                                                 {"Ę", "&#280;"},
                                                                                 {"Ā", "&#256;"},
                                                                                 {"ā", "&#257;"},
                                                                                 {"Ă", "&#258;"},
                                                                                 {"ă", "&#259;"},
                                                                                 {"Ǟ", "&#478;"},
                                                                                 {"ǟ", "&#479;"},
                                                                                 {"Ǻ", "&#506;"},
                                                                                 {"ǻ", "&#507;"},
                                                                                 {"Ǽ", "&#508;"},
                                                                                 {"ǽ", "&#509;"},
                                                                                 {"Ḃ", "&#7682;"},
                                                                                 {"ḃ", "&#7683;"},
                                                                                 {"Ć", "&#262;"},
                                                                                 {"ć", "&#263;"},
                                                                                 {"Č", "&#268;"},
                                                                                 {"č", "&#269;"},
                                                                                 {"Ĉ", "&#264;"},
                                                                                 {"ĉ", "&#265;"},
                                                                                 {"Ċ", "&#266;"},
                                                                                 {"ċ", "&#267;"},
                                                                                 {"Ḑ", "&#7696;"},
                                                                                 {"ḑ", "&#7697;"},
                                                                                 {"Ď", "&#270;"},
                                                                                 {"ď", "&#271;"},
                                                                                 {"Ḋ", "&#7690;"},
                                                                                 {"ḋ", "&#7691;"},
                                                                                 {"Đ", "&#272;"},
                                                                                 {"đ", "&#273;"},
                                                                                 {"DZ", "&#497;"},
                                                                                 {"Dz", "&#498;"},
                                                                                 {"dz", "&#499;"},
                                                                                 {"DŽ", "&#452;"},
                                                                                 {"Dž", "&#453;"},
                                                                                 {"dž", "&#454;"},
                                                                                 {"Ě", "&#282;"},
                                                                                 {"ě", "&#283;"},
                                                                                 {"Ē", "&#274;"},
                                                                                 {"ē", "&#275;"},
                                                                                 {"Ĕ", "&#276;"},
                                                                                 {"ĕ", "&#277;"},
                                                                                 {"Ė", "&#278;"},
                                                                                 {"ė", "&#279;"},
                                                                                 {"Ʒ", "&#439;"},
                                                                                 {"ʒ", "&#658;"},
                                                                                 {"Ǯ", "&#494;"},
                                                                                 {"ǯ", "&#495;"},
                                                                                 {"Ḟ", "&#7710;"},
                                                                                 {"ḟ", "&#7711;"},
                                                                                 {"ƒ", "&#402;"},
                                                                                 {"ff", "&#64256;"},
                                                                                 {"fi", "&#64257;"},
                                                                                 {"fl", "&#64258;"},
                                                                                 {"ffi", "&#64259;"},
                                                                                 {"ffl", "&#64260;"},
                                                                                 {"ſt", "&#64261;"},
                                                                                 {"Ǵ", "&#500;"},
                                                                                 {"ǵ", "&#501;"},
                                                                                 {"Ģ", "&#290;"},
                                                                                 {"ģ", "&#291;"},
                                                                                 {"Ǧ", "&#486;"},
                                                                                 {"ǧ", "&#487;"},
                                                                                 {"Ĝ", "&#284;"},
                                                                                 {"ĝ", "&#285;"},
                                                                                 {"Ğ", "&#286;"},
                                                                                 {"ğ", "&#287;"},
                                                                                 {"Ġ", "&#288;"},
                                                                                 {"ġ", "&#289;"},
                                                                                 {"Ǥ", "&#484;"},
                                                                                 {"ǥ", "&#485;"},
                                                                                 {"Ĥ", "&#292;"},
                                                                                 {"ĥ", "&#293;"},
                                                                                 {"Ħ", "&#294;"},
                                                                                 {"ħ", "&#295;"},
                                                                                 {"Ĩ", "&#296;"},
                                                                                 {"ĩ", "&#297;"},
                                                                                 {"Ī", "&#298;"},
                                                                                 {"ī", "&#299;"},
                                                                                 {"Ĭ", "&#300;"},
                                                                                 {"ĭ", "&#301;"},
                                                                                 {"Į", "&#302;"},
                                                                                 {"į", "&#303;"},
                                                                                 {"İ", "&#304;"},
                                                                                 {"ı", "&#305;"},
                                                                                 {"IJ", "&#306;"},
                                                                                 {"ij", "&#307;"},
                                                                                 {"Ĵ", "&#308;"},
                                                                                 {"ĵ", "&#309;"},
                                                                                 {"Ḱ", "&#7728;"},
                                                                                 {"ḱ", "&#7729;"},
                                                                                 {"Ķ", "&#310;"},
                                                                                 {"ķ", "&#311;"},
                                                                                 {"Ǩ", "&#488;"},
                                                                                 {"ǩ", "&#489;"},
                                                                                 {"ĸ", "&#312;"},
                                                                                 {"Ĺ", "&#313;"},
                                                                                 {"ĺ", "&#314;"},
                                                                                 {"Ļ", "&#315;"},
                                                                                 {"ļ", "&#316;"},
                                                                                 {"Ľ", "&#317;"},
                                                                                 {"ľ", "&#318;"},
                                                                                 {"Ŀ", "&#319;"},
                                                                                 {"ŀ", "&#320;"},
                                                                                 {"Ł", "&#321;"},
                                                                                 {"ł", "&#322;"},
                                                                                 {"LJ", "&#455;"},
                                                                                 {"Lj", "&#456;"},
                                                                                 {"lj", "&#457;"},
                                                                                 {"Ṁ", "&#7744;"},
                                                                                 {"ṁ", "&#7745;"},
                                                                                 {"Ń", "&#323;"},
                                                                                 {"ń", "&#324;"},
                                                                                 {"Ņ", "&#325;"},
                                                                                 {"ņ", "&#326;"},
                                                                                 {"Ň", "&#327;"},
                                                                                 {"ň", "&#328;"},
                                                                                 {"ʼn", "&#329;"},
                                                                                 {"Ŋ", "&#330;"},
                                                                                 {"ŋ", "&#331;"},
                                                                                 {"NJ", "&#458;"},
                                                                                 {"Nj", "&#459;"},
                                                                                 {"nj", "&#460;"},
                                                                                 {"Ō", "&#332;"},
                                                                                 {"ō", "&#333;"},
                                                                                 {"Ŏ", "&#334;"},
                                                                                 {"ŏ", "&#335;"},
                                                                                 {"Ő", "&#336;"},
                                                                                 {"ő", "&#337;"},
                                                                                 {"Ǿ", "&#510;"},
                                                                                 {"ǿ", "&#511;"},
                                                                                 {"Œ", "&#338;"},
                                                                                 {"œ", "&#339;"},
                                                                                 {"Ṗ", "&#7766;"},
                                                                                 {"ṗ", "&#7767;"},
                                                                                 {"Ŕ", "&#340;"},
                                                                                 {"ŕ", "&#341;"},
                                                                                 {"Ŗ", "&#342;"},
                                                                                 {"ŗ", "&#343;"},
                                                                                 {"Ř", "&#344;"},
                                                                                 {"ř", "&#345;"},
                                                                                 {"ɼ", "&#636;"},
                                                                                 {"Ś", "&#346;"},
                                                                                 {"ś", "&#347;"},
                                                                                 {"Ş", "&#350;"},
                                                                                 {"ş", "&#351;"},
                                                                                 {"Š", "&#352;"},
                                                                                 {"š", "&#353;"},
                                                                                 {"Ŝ", "&#348;"},
                                                                                 {"ŝ", "&#349;"},
                                                                                 {"Ṡ", "&#7776;"},
                                                                                 {"ṡ", "&#7777;"},
                                                                                 {"ſ", "&#383;"},
                                                                                 {"Ţ", "&#354;"},
                                                                                 {"ţ", "&#355;"},
                                                                                 {"Ť", "&#356;"},
                                                                                 {"ť", "&#357;"},
                                                                                 {"Ṫ", "&#7786;"},
                                                                                 {"ṫ", "&#7787;"},
                                                                                 {"Ŧ", "&#358;"},
                                                                                 {"ŧ", "&#359;"},
                                                                                 {"Ũ", "&#360;"},
                                                                                 {"ũ", "&#361;"},
                                                                                 {"Ů", "&#366;"},
                                                                                 {"ů", "&#367;"},
                                                                                 {"Ū", "&#362;"},
                                                                                 {"ū", "&#363;"},
                                                                                 {"Ŭ", "&#364;"},
                                                                                 {"ŭ", "&#365;"},
                                                                                 {"Ų", "&#370;"},
                                                                                 {"ų", "&#371;"},
                                                                                 {"Ű", "&#368;"},
                                                                                 {"ű", "&#369;"},
                                                                                 {"Ẁ", "&#7808;"},
                                                                                 {"ẁ", "&#7809;"},
                                                                                 {"Ẃ", "&#7810;"},
                                                                                 {"ẃ", "&#7811;"},
                                                                                 {"Ŵ", "&#372;"},
                                                                                 {"ŵ", "&#373;"},
                                                                                 {"Ẅ", "&#7812;"},
                                                                                 {"ẅ", "&#7813;"},
                                                                                 {"Ỳ", "&#7922;"},
                                                                                 {"ỳ", "&#7923;"},
                                                                                 {"Ŷ", "&#374;"},
                                                                                 {"ŷ", "&#375;"},
                                                                                 {"Ÿ", "&#376;"},
                                                                                 {"Ź", "&#377;"},
                                                                                 {"ź", "&#378;"},
                                                                                 {"Ž", "&#381;"},
                                                                                 {"ž", "&#382;"},
                                                                                 {"Ż", "&#379;"},
                                                                                 {"ż", "&#380;"}
                                                                             };
        #endregion

        /// <summary>
        /// A fuller html encoding than the built in method, will encode a large number of characters ignored by the built in method including apostrophes.
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string EncodeFull(this HtmlHelper helper, string html)
        {
            var result = helper.Encode(html);
            foreach (var replacement in Replacements)
            {
                result = result.Replace(replacement.Key, replacement.Value);
            }
            return result;
        }
    }
}

And here is a unit test for it, this uses the HtmlHelperFactory class I described here:

using System.Linq;
using System.Web.Routing;
using KableDirect.Web.FrontEnd.Helpers;
using MbUnit.Framework;

namespace KableDirect.UnitTests
{
    [TestFixture]
    public class TestHtmlEncode
    {
        [Test]
        public void test_all_chars_are_encoded()
        {
            var html = HtmlHelperFactory.CreateInstance(new RouteData());
            var specials = "–—‘’‚“”„†‡•…‰€™ŒœŠšŸƒ’ÀàÁáÂâÃãÄäÅåĀāĂ㥹ǞǟǺǻÆæǼǽḂḃĆćÇçČčĈĉĊċḐḑĎďḊḋĐđÐðDZDzdzDŽDždžÈèÉéĚěÊêËëĒēĔĕĘęĖėƷʒǮǯḞḟƒfffiflffifflſtǴǵĢģǦǧĜĝĞğĠġǤǥĤĥĦħÌìÍíÎîĨĩÏïĪīĬĭĮįİıIJijĴĵḰḱĶķǨǩĸĹĺĻļĽľĿŀŁłLJLjljṀṁŃńŅņŇňÑñʼnŊŋNJNjnjÒòÓóÔôÕõÖöŌōŎŏØøŐőǾǿŒœṖṗŔŕŖŗŘřɼŚśŞşŠšŜŝṠṡſßŢţŤťṪṫŦŧÞþÙùÚúÛûŨũÜüŮůŪūŬŭŲųŰűẀẁẂẃŴŵẄẅỲỳÝýŶŷŸÿŹźŽžŻż";
            var encoded = html.EncodeFull(specials);
            var specialChars = specials.ToCharArray();
            var missedChars = encoded.ToCharArray().Intersect(specialChars);
            string output = "";
            foreach(var ch in missedChars)
            {
                output += "{\"" + ch + "\", \"&#" + ((int) ch) + ";\"},\n";
            }
            Assert.IsEmpty(output);
        }
    }
}
 

Ruby’s ‘times()’ function in C# January 24, 2010

Filed under: C#,Coding,Uncategorized — Rupert Bates @ 10:20 pm

I’ve seen a lot of people enthuse about Ruby’s times() function which allows you to write code like:

5.times { |i| puts i }

which prints out:
0
1
2
3
4
It is a really nice syntax and it struck me that you could use similar syntax in C# by defining the following extension method on int:

public static class IntExtensions
{
	public static void Times(this int i, Action<int> func)
	{
		for(int j = 0; j < i; j++)
		{
			func(j);
		}
	}
}

Which then lets you write:

5.Times(i => Console.Write(i));

with the same results