Monday 27 June 2011

CSS border-radius and background problem

I think I'm a fairly typical developer in that doing front end work is something I'm not very good at and simply have to put up with. That being the true I normally wouldn't bother blogging about it. But in this case I came across an odd problem which confused my tiny brain, so I thought it worth writing some guff about. 

My problem was this: I wanted rounded corners on my table and an alternating colour for each row. I did it using this CSS:

.myTable tbody tr:nth-child(2n) td, tbody tr.even td {
  background: none repeat scroll 0 0 #eaeaea;
}

.myTable {
  border: 1px solid black;
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
  border-radius: 4px;
}

The result is shown below. This happened on both bottom corners, but only when a background was applied (i.e. an even row):

If you can't see that, my rounded corner is missing a few pixels. What the hell is going on? The rounded corners were perfect when there was no background colour. After a fair amount of messing about in Firebug I came to the conclusion that the background colour was somehow conflicting with the rounded corners. My solution/hack was to add some CSS to specifically set the rounded corners of the at the bottom of the table. Why only the bottom corners? Because I have defined a background colour on even rows only and the top row will obviously always be odd.

.myTable tr:last-child td:last-child {
  -moz-border-radius: 0 0 4px 0;
  -webkit-border-radius: 0 0 4px 0;
  border-radius: 0 0 4px 0;
}
.myTable tr:last-child td:first-child {
  -moz-border-radius: 0 0 0 4px;
  -webkit-border-radius: 0 0 0 4px;
  border-radius: 0 0 0 4px;
}

Wednesday 15 June 2011

Ninject and ASP.NET MVC 3 - Surely it can't be that easy?

Over the past couple of weeks I've started to rewrite a project I wrote a few years ago using Sharp Architecture and ASP.NET MVC 1. I wanted to update to ASP.NET MVC 3 and remove the dependency on Sharp Architecture which would force me to implement a lot more functionality myself, and therefore (hopefully) increase my understanding. One of the tasks I've been putting off is choosing a dependency injection container. I've had a little experience of Castle and Unity and they both seemed fine, but to be honest, I wanted to be really lazy and implement dependency injection with the least amount of effort. Enter Ninject. The only reason I started reading about Ninject was because I liked the name. But, turns out my random affinity for something I knew nothing about based on the name alone turned up trumps. 

At lunchtime today I read some of the Ninject documentation. Turns out there is a Ninject extension for MVC 3 and a convention extension which should, in theory, allow for code without loads of bind commands. Sounds promising. The good news is that the Ninject documentation is very good and the MVC 3 extension documentation is good. The bad news is that the convention extension documentation is seemingly non-existent. I certainly couldn't find much useful documentation anyway. But, I gave it a shot anyway, and in about an hour or so I had functioning dependency injection with minimal code. It was so simple I thought I must have made a mistake. But no, it works. I'm not sure it was the best solution but I don't care, it works. 

Before I continue it's worth me explaining some my basic project structure. It's nothing fancy. I've separated data access, service and web stuff into separate projects. All my classes follow a convention like SomeController, SomeService, SomeRepository, ISomeService, etc. All the classes has parameterless constructors. So it's helpfully simple. Anyway, here is what I did.

Firstly I installed Ninject and the Ninject MVC 3 extension using Nuget as described here.

I then installed the Ninject conventions extension using Nuget.

In the NinjectMVC3.cs file created by the Ninject MVC 3 plugin I changed the CreateKernal method to the following:

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();

    var scanner = new AssemblyScanner();
    scanner.FromAssembliesMatching("Basketball.Logic.dll"); // Services classes here
    scanner.FromAssembliesMatching("Basketball.Data.dll");  // Repositories here
    scanner.BindWithDefaultConventions();

    kernel.Scan(scanner);

    return kernel;

And that's it. It worked. An instance of my repository class was injected into my service class and an instance of my service class was injected into my controller class. High five! In addition when I add a new controller/service/repository there's no need to add any further Ninject binding code. Brilliant!