find a location for property in a new city

Thursday, 14 October 2010

Don't fuck with the repository or unit of work pattern

I am one for not taking patterns as gospel so I have a tendency to use the bits I want and discard the bits I don't. Today I discovered I don't necessarily know best.

At lovemoney.com I have just started using Unity 2.0 to replace Spring.NET as our dependency container. This has meant that I have had to reimplement some of the wiring of the dependencies. This includes our implementation of the Repository pattern for use with Entity Framework.

Now, my problem with the Repository pattern is that I have always struggled to see the point in the UnitOfWork part of the pattern. Just extra typing for me with no/little benefit. I decided that (as with most things I don't understand) they should prove their worth. Reading didn't help their cause so I went for the more drastic way of not using and see what goes wrong. Well, nothing did! So there it is I will never use the Unit of Work pattern again.

Until today that is.

Here is a snippet from my EntityRepository:
public ObjectContext Context { get; private set; }
//in an orthodox implementation this would accept a UnitOfWork instead of an ObjectContext
public EntityRepository(ObjectContext context)
{
    Context = new UnitOfWork(context).Context;
}

And here is the wiring in my Unity configuration:
var container = new UnityContainer();

//content repositories
container.RegisterType<IRepository<LoveContent>, EntityRepository<LoveContent>>(new InjectionConstructor(new ContentEntities()))

Something just wasn't right. I first noticed it when I created a new item and added it to the repository and then tried to delete it. Well deleting the item wasn't the problem, it was the repository knowing what had happened. I deleted the item and it was gone, gone from the database, gone from the data returned from the database but not gone from the Repository when it came to display the results on the page.

So, I figured this was something to do with my bastardisation of the Repository and Unit of Work pattern. I configured Unity correctly to implement this pattern and lo it worked as expected.

So I won!

Well, sort of. I know I thought best, it turned out I didn't, then I came crawling back to convention. But I think I am better off for it. If I had just done what all of the blogs had told me I wouldn't have understood why I was doing it.

Being a curious chap I like to understand everything I use and this has helped me. Hopefully it will help you too if you are scratching your head at the Unit of Work pattern.

But seriously, how do you solve it?

If you are/were struggling with this I have written another blog post that will tell you how to set up the repository pattern with Unit of Work using Unity 2.0.

Follow britishdev on Twitter

Wednesday, 6 October 2010

ASP.NET Authentication cookie not persisting across servers and subdomains

Recently some internal users have started complaining about being sporadically logged out and having to log in again when accessing a different server or different sub domain. It seems like the ASP.NET security cookie is not being persisted between live production servers and development servers.

I noticed a pattern to the seemingly spurious logging out and having to log in again:

  • Log in on live or if you are already logged in. Fine.
  • Log in on your development machine. (Oh that's weird, I thought I was logged in... but okay maybe I wasn't). Fine.
  • Refresh your page on the live site and I need to login again.

Why won't my cookie persist?! Why am I being logged out?

This has started happening since the recent ASP.NET security fix was put on our servers. Apparently it is something to do with changing the necessary authentication cookie. I guess in case you were already exploited before the security fix went out. Anyway, if you are swapping between non-patched development servers and patched production servers you're cookie will NOT persist and you will be asked to log in again if authentication or authorization is demanded by your page.

So either:
  1. Install the patch on all servers as per the ASP.NET team's advice
  2. OR be content with the fact that your customers won't have the problem. (Unless you have both patched and non-patched servers in your web farm)

Follow britishdev on Twitter

Friday, 1 October 2010

ASP.NET MVC IsAjaxRequest() not recognising request from jQuery $.ajax()

If you are finding that an AJAX request from, say, a piece of jQuery AJAX code such as $.ajax() $.get() or $.post() or you own custom AJAX code (you legend) is not registering as an AJAX request when using the IsAjaxRequest() then the problem is probably to do with X-Requested-With.

I used .NET Reflector to have a look at how IsAjaxRequest() works and it is something like this:
return ((request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest")));

So that means you need to have a header of "X-Requested-With" set to "XMLHttpRequest" which is usually the case when you are using AJAX libraries like ASP.NET's or jQuery's. You can see if this is the case using Fiddler.

However, interestingly you can also set this as either part of your form POST or even a GET querystring! Such as www.example.com?x-requested-with=XMLHttpRequest (case sensitive). This will also make IsAjaxRequest() return true.

Follow britishdev on Twitter

Thursday, 23 September 2010

Get all month names from DateTime in C# programatically

I needed to have a drop down list of all the months but I don't want to be writing all of that out. So is there a way to list all the months programmatically in C#. Hell yeah there is

I knew there would be a way to do it and I knew it would be something to do with the CultureInfo of the session.

Here is a method I wrote to return a set of key values for each month:
public IEnumerable<KeyValuePair<int, string>> GetAllMonths()
{
 for (int i = 1; i <= 12; i++)
 {
  yield return new KeyValuePair<int, string>(i, DateTimeFormatInfo.CurrentInfo.GetMonthName(i));
 }
}

Just to demonstrate, I used it in my ASP.NET MVC app:
<%: Html.DropDownListFor(model => model.DobMonth, new SelectList(Model.GetAllMonths(), "Key", "Value", Model.DobMonth)) %>

Which outputs the following HTML:
<select id="DobMonth" name="DobMonth">
<option selected="selected" value="1">January</option> 
<option value="2">February</option> 
<option value="3">March</option> 
<option value="4">April</option> 
<option value="5">May</option> 
<option value="6">June</option> 
<option value="7">July</option> 
<option value="8">August</option> 
<option value="9">September</option> 
<option value="10">October</option> 
<option value="11">November</option> 
<option value="12">December</option> 
</select>

Follow britishdev on Twitter

Bet you didn't know about: C# Numerical suffixes

I love learning new things and you probably do too. So how about this one... I found a way to make a long, double, unsigned int etc without having to use casting or having to explicitly declare the type.

Instead of using explicit declarations and casting like this:

long l = 12;
var d = (double)12;
float f = 12.0; //compilation error
var u = (UInt32)12;
decimal m = 12;
ulong ul = 12;

You can use the numerical suffixes like this:

var l = 12L;
var d = 12D;
var f = 12.0F;
var u = 12U;
var m = 12M;
var ul = 12UL;

So there we are. Interesting? Or maybe everyone already knew that and I've only just found it.

Follow britishdev on Twitter

Wednesday, 15 September 2010

Using Application State as early as possible in ASP.NET MVC

I'm working on a new website that will run off the same architecture as lovemoney.com. To distinguish one site from the other I am using a variable stored in ApplicationState. However I was running into problems when trying to access this variable.

The problem was that I was setting the Application variable in Application_Start() of Global.asax. I was accessing this variable in the contructor of my base Controller (that all my Controllers inherit from).

This was too early. Not too early for the Application_Start() event, obviously. Just too early to be able to access it I assume.

So how early can I access ApplicationState?

I found I could access it without problem on the Initialize method of my BaseController:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
    //only here is the application state finally ready to be set
    SiteID = (int)requestContext.HttpContext.Application["SiteID"];
}

Problem is I really want to be able to access it during construction of my BaseController though since I will be implementing DI shortly. So in the end I used AppSettings in the config instead which can be accessed in the constructor. Still, this will still be useful I'm sure.

Follow britishdev on Twitter

Monday, 6 September 2010

How to force clients to hard refresh their browser cache

We had this problem when we removed our style sheets and put them into a HttpHandler to serve them all in one single request. The problem was that due to some caching problem, users' needed to refresh their page to receive the updated CSS files. This resulted in confused users looking at a non-styled site featuring trendy black Times New Roman font on a original white background with blue and purple retro links? old skool...

We (as developers) nonchalantly refreshed the page and happily continued, others didn't and we quickly realised that "Oh, they just need to refresh the page" wasn't good enough.

Solution

We needed a way to make the users refresh their browser caches, but how since we have no control over their browsers?

I came up with a bit of JavaScript that will do a hard refresh of the page and use cookies to record that it has been refresh and ensure that it only happens once and doesn't go into an infinite loop.

Here is some code I came up with:
//jquery plugin for cookies
<script type="text/javascript" src="/js/jquery/jquery.cookies.2.0.1.min.js"></script>
<script type="text/javascript">
//give it a new name each time you need to do this
var cookieName = 'refreshv1';
//check client can use cookies
if ($.cookies.test()) {
    //get the cookie
    var c = $.cookies.get(cookieName);
    //if it doesn't exist this is their first time and they need the refresh
    if (c == null) {
        //set cookie so this happens only once
        $.cookies.set(cookieName, true, { expires: 7 });
        //do a "hard refresh" of the page, clearing the cache
        location.reload(true);
    }
}
</script>
Feel free to work with this code but please do not use it without testing or ensuring it is right for your situation. It is merely an idea that worked for me.

Follow britishdev on Twitter

Thursday, 19 August 2010

Generate lowercase URLs with T4MVC templating tool

I noticed that my URL paths that are being generated using using T4MVC's excellent MVC templating were coming out in title case. This is a problem since we try to keep all URLs lower case since Google deems URL in different cases showing the same result as duplicate content.

I looked through a lot of the code that is generated by the tool and traced the problem all the way to the MyController.generated.cs file:
public class ActionNamesClass {
    public readonly string Index = "Index";
    public readonly string Edit = "Edit";
    public readonly string Create = "Create";
}

Great now I have to edit the way the code is generated... or do I?

Solution

Turns out David Ebbo has thought of everything! There is a setting in the T4MVC.settings.t4 file specifically for that, which I just need to set to true:
// If true, use lower case tokens in routes for the area, controller and action names
const bool UseLowercaseRoutes = true;

Now when I look at the generated code in my MyController.generated.cs file I can see:
public class ActionNamesClass {
    public readonly string Index = ("Index").ToLowerInvariant();
    public readonly string Edit = ("Edit").ToLowerInvariant();
    public readonly string Create = ("Create").ToLowerInvariant();
}

Lovely.

Follow britishdev on Twitter

Thursday, 12 August 2010

Remove HTTP response headers to hide your framework

There are a number of infrastructure details that are passed with your HTTP response headers when serving a page. The security conscious developers out there will be aware that hackers and other malicious people will enjoy learning that information to target their exploits for that framework. If you want to remove the HTTP response headers of Server, X-Powered-By, X-AspNet-Version, X-AspNetMvc-Version or any others I will show you how.

I will show you the less hacky ones first. I.e. the ones where it is designed for you to remove them easily:

X-AspNet-Version

This can be removed simply using the enableVersionHeader attribute of the httpRuntime section of system.web section of your web.config:
<system.web>
  <httpRuntime enableVersionHeader="false" />
  <!-- other settings -->
</system.web>

X-AspNetMvc-Version

In your Global.asax.cs you can add the following to your Application_Start method:
protected void Application_Start(object sender, EventArgs e)
{
    MvcHandler.DisableMvcResponseHeader = true;
    // RegisterRoutes etc... and other stuff
}

X-Powered-By

Instead of removing this I have decided to change it to something different so as not to cause suspicion to a potential hacker:
<system.webServer>
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By"/>
      <add name="X-Powered-By" value="PHP 5.2 Ubuntu"/>
    </customHeaders>
  </httpProtocol>
  <!-- other stuff -->
</system.webServer>

Server

This one is harder since you can't actually do it anywhere else. Of course you could have changed all the other Headers here too but it feels messy doing it this way so I opted to change the others using the intended way.

First, make an HttpModule (essentially a class inheriting from IHttpModule) like this:
namespace HttpModules
{
    public class SecurityModule : IHttpModule
    {
        public void Dispose()
        {
            //intentionally do nothing
        }

        public void Init(HttpApplication context)
        {
            context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders);
        }

        private void context_PreSendRequestHeaders(object sender, EventArgs e)
        {
            var context = ((HttpApplication)sender).Context;
            context.Response.Headers.Set("Server", "Apache 2.0");
        }
    }
}
Note: I have gone for lying about the server over removing it (which is also possible) since I'd rather fool hackers than annoy them.

Next you just need to register that module in your web.config:
<system.webServer>
  <modules>
    <add name="SecurityModule" type="HttpModules.SecurityModule, HttpModules" />
  </modules>
</system.webServer>

Now use Fiddler to have a look at your Response Headers. Hopefully wonderfully deceptive like this:

If you have more to remove/change you can do it in much the same way as X-Powered-By (using web.config) or if not the Server one (using the Security HttpModule).

Follow britishdev on Twitter

Wednesday, 4 August 2010

IntelliSense for jQuery in Visual Studio 2010

I read this morning in Steve Sanderson's Pro ASP.NET MVC 2 Framework book that it is possible to get IntelliSense when using the popular JavaScript library, jQuery.

Microsoft have decided to implicitly support jQuery by including some of its libraries in their sample MVC project. This is as well as their own AJAX library that comes with a lot of support for ASP.NET Web Forms specific features, which of course you won't be needing in ASP.NET MVC.

Part of their support translates into working with them to provide IntelliSense support to Visual Studio. It is not entirely integrated so will need a touch of set up and here's how to do it:

Let's do it!

First, you need to get the jquery-1.4.1-vsdoc.js file. I got mine by creating a new ASP.NET MVC2 sample web application. You will find it at /Scripts/jquery-1.4.1-vsdoc.js. Copy it from here and put it in your application somewhere sensible.

Then you simply reference the file like so:
<% /* %><script type="text/javascript" src="/js/jQuery/jquery-1.4.1-vsdoc.js"></script><% */ %>

Now you can enjoy such delights as this:

Note

  • You may want to put that reference in your MasterPage so it will work for all pages that use it. It will not work in miscellaneous pages or user controls (unless you add your own reference in those pages).
  • Also note the syntax I used so that users will not download the file as part of their request.
  • This works for VS2010. For VS2008 you may need to download a path that allows Visual Studio to find *-vsdoc.js files automatically

Follow britishdev on Twitter