Wednesday 21 March 2012

Cross Browser CSS Done With Ease In MVC

As anyone meddling with CSS on a daily basis knows, one of the biggest headaches is how to handle the subtle differences in how different browsers like to render your pages. Naming no names but far the worst offenders seem to be the earlier versions of Internet Explorer... but every now and again other browsers have their moments too. And as more and more browser versions and devices are becoming available, this issue could still be around for a long time yet.

You can get a copy of the source code here.

Our site has just been through a redesign and this problem reared it's head once again so rather than try and get around issues with the different hacks people have written about before (prefixing IE specific CSS with an asterisk etc etc), I came up with a simple but reasonably elegant way of doing this, without the need for the browser to be requesting it's own style sheet to override the main style sheet.

First of all we need to determine the browser making the request. I chose to do this by creating an Html Extension Method so we can encapsulate all this logic behind a nice clean method to use in our Razor view.



The GetBrowserDetails method is a little messy but anyone who has messed around with the user agent string will know it's a little confusing and even though it looks like a browser can be one type, it's actually another (this is mainly around Safari for some reason). The main thing is it works across IE(6-9), Firefox, Chrome and Safari (including iPad and iPhone). It can obviously be amended and extended as anyone sees fit.

But essentially that is it, I just need to use the string returned as my class in my Razor views. I have added it right at the top to my <body> tag, this way it only needs to be used once and we can override anything in our page from here. So in my _Layout.cshtml...

And now when you browse your site your <body> tag should have a class relating to the browser you are using.

Now all that is left to do is override these styles to get the desired affect, for example if you wanted to change all the <h2> tags in your site to different colours according to it's browser type...

Obviously I would expect people would use this to help with more serious rendering issues (paddings and margins etc) but you get the point, I can target any element on the page and change it according to how I want a certain browser to render it. And once the simple foundations are in place, it's very easy to do in my CSS.

Not only that, but since it's all based around CSS selectors, you can now easily target browser specific elements in jQuery too, just in case you want to disable that pop out menu that doesn't work properly in IE 6!

You can get a copy of the source code here.

If you have any thoughts or comments then please let me know.

Thanks
Jason

Friday 3 February 2012

Issue - No parameterless constructor defined for this object using Ninject in MVC3

A recent issue that got me puzzled for a small while recently was this on the yellow screen of death...

Server Error in '/' Application.
No parameterless constructor defined for this object.

In the stack trace were the following key lines
[MissingMethodException: No parameterless constructor defined for this object.]

and

[InvalidOperationException: An error occurred when trying to create a controller of type 'JasonpDoherty.Controllers.TestController'. Make sure that the controller has a parameterless public constructor.]


This confused me at first as I hadn't made any changes to any constructors during this piece of work so why had it started to complain about this now? What was even more confusing was the fact every other controller could be constructed except for this one.

I have been using Ninject for my sites and I love it. It's pretty lightweight but at the same time gives you a solid dependency injection solution for MVC3. There are tonnes of tutorials to get you going once you have downloaded the package from Nuget.

The problem is that the whole point of using Ninject in my MVC projects is so I can inject dependencies into my controllers? So why am I being told that my controller need a parameterless constructor?

After applying a bit of hindsight I realised what had happened...

My controller constructor is made up like this



I have just created another service that IStockService depends on called IReservationService. This is injected into the IStockService via the constructor. I don't need to inject a concrete version manually because Ninject will do this for me.

And the problem lies here, I actually forgot to tell Ninject to bind IReservationService to anything concrete in my Global.asax, and because I forgot to do this, Ninject did not know how to create an instance of IReservationService, and therefore could not create an instance of IStockService which in turn could not create me an instance of my controller. So instead it tries to find a default constructor in the controller of which I don't have (or want) one.

The problem isn't always that obvious because you could be working way down at another level well away from your UI/Controller and yet the exception you see indicates something is wrong with the way you have created your controller. So it's something to watch out for.

I guess the fix is to create concrete versions of your Interfaces you intend to inject with Ninject, and bind these to your interfaces in your Global.asax straight after, even if they are stubbed ones whilst you are progressing through your work.

Let me know if you have any comments or queries.

Thanks
Jason

Thursday 24 November 2011

Redirecting from non www to www

For some reason I always tend to forget how to do this, so since I have recently just done this for a site, I thought I would get it down in a blog, as much for my own reference as anything else! Obviously feel free to use if you come across this and it is useful to you :)

As everyone knows search engines will treat http://domain.com and http://www.domain.com as two completely different urls, therefore if they have both indexed against your site you be penalised for duplicate content, and that is not a good thing.

So before Google/Bing and the rest find out about your site, it is best to get this in place in your web config file nice and early (by early I mean from first live deployment onwards!). This config assumes you are running your site on IIS7.



This goes in the <system.webServer> section, and will automatically re-direct anyone coming in without the www in their url, over to the www version without them noticing.

Looking with fiddler (or any other proxy tool where you can analyse http requests and responses) I cannot see any actual 301 statuses, which will not matter if you get this into your config early enough. Search engines (and anyone using links from the site) will only ever know one version so it should be happy days.

I know this nothing new and there are lots of places where it is always documented, but in each case it seems to be slightly different, and this seems to work for my the best so far.

Thanks
Jason

Thursday 30 June 2011

Generate Directions Using Google Maps Javascript API

A sample project for this can be found here...

It's common on the web, to want to explain exactly where your office, shop or restaurant is, and there are different ways you can do this, you could simply stick your address on a contact us page, and let potential customers find your location for themselves, or you could get the details on the google maps site and create a link to the generated google url on your site, or could could even display a map image to give a customer an idea where you are hiding!

I was recently asked come up with a solution allow customers to be able to not only easily view my company's location on an interactive map, but also be able to input their own location, only for the web site to give directions, a summary of distance and time and also an updated route map. This solution would need to solve the problems generated by the alternative methods I mentioned:

  • Users would not be directed away from the site (or even page) to get information about the journey.
  • Users would be able to get exact information about their journey, not just your location.
  • It is essential to give the users a good experience, if the correct information tailored to them is available with a couple of keypresses and the click of a mouse button, there is more chance of them being impressed and maybe just turning up at your store.
Google's Javascript API fits the bill perfectly for this, there is loads of documentation out there on how to use it, but since I have cobbled the base of the code altogether into a little R&D project, thought it would be a good thing to share, as I struggled to find a sample project I could download and have a look at.

The project itself is done in MVC3 using Razor, the reasoning behind this I needed to go one step further and determine the the nearest store to the users postcode, I achieved this with a jQuery request to the server that handled the request and returned the nearest site's postcode, ready for me to port into my actual site, it's not relavent to this post so it's not included in this post, but it's pretty straight forward...

The bones of this small project is purely Html and javascript/Jquery so feel free to import into your own project. The UI is basically a origin text box, destination text box, and a map place holder...

The sample code can be found here...

One more note...
The Google API adds some styles to the map place holder that initially will make the page look a bit odd ,so have a look in the CSS for how I got round this at the bottom of the site.css, you can then extend on this to get it exactly how you want it for your own site.

Please let me know your thoughts and comments

Thanks
Jason

Monday 30 May 2011

Create a custom MVC Html Helper Method For ToolTips

HtmlHelper methods in MVC are great, they cut down on so much code, your view markup looks so much cleaner and so much more readable, they interact with your model and in general are very widely used. One of the great things about the HtmlHelper (and MVC in general) class is it's extensibility, you can quite easily create your own extension methods and create lots of extra re-usable functionality throughout your site. There is a small bit of work involved in the set up but I have found it's well worth it.

This post expects you have some experience in creating simple MVC projects.

This particular helper method is designed to allow a developer to easily add tool tips to various elements on their MVC web site, the goal is to be able to do something like this in your view

@Html.TextBoxFor(x => x.Name)
@Html.ToolTipMessageFor(x => x.Name)

When the text box is in focus, the ToolTip should render, when the text box loses focus it will vanish.

How to do it...

So go ahead and create yourself a new MVC3 (I am using Razor as a View Engine (I always do) but you can modify the appropriate markup easily enough) project called HtmlHelperExample, just select the defaults for the project (not a completely empty project as we will use the generated controllers etc).

Create yourself a model in the Models folder, I have created one called Player that will look a little like this...




We are then going to create a new attribute we can decorate these properties with, called ToolTip.

In order to do this, we need to create a new folder (to keep things nice and neat of course) called Attributes, and in there a new class called ToolTipAttribute, this class is going to inherit from System.ComponentModel.DescriptionAttribute, the reason we create a new class is in case we want to override any default behaviour and also distinguish between what a ToolTipAttribute and a DescriptionAttribute mean, you could have both attributes on a property that do two different things.

Last thing we need to do with this, is set up a constructor that in turn call the base constructor, I am also hiding the default constructor to force a message to be set every time a ToolTip attribute is constructed. When finished, the class will look like this.

Build the project and you can now decorate your player class in the usual way but now the ToolTip attribute is available. Add a Required attribute to the Position property, will explain why in a little bit...


Create a typical action result on the Home Controller called AddPlayer, and add a view (it should be strongly typed using our Player class) for this for adding a player to an imaginery database/repository, and start the project to make sure you can browse to the page, click submit and you should get an validation error moaning about the Position field being required, and also the NumberOfPremiershipsWon will complain as it is an integer and the javascript doesn't infer empty text boxes as zeroes.




Now I have a working project that expects a model that contains properites decorated with our ToolTip method, we are now ready to start building our HtmlHelper Method class.

Create a new folder in the project called HtmlHelperExtensions, and in here create a class called ToolTipHelper. This class needs to be static as we are going to be creating a an extension method in here shortly.

Have a think about the 3 @Html.ValidationMessageFor we have just created (if you used the VS2010 scaffolding wizard), we basically pass in a lambda expression from our model explaining what we want to validate, and it returns a piece of Html based on the attributes of that property, this is exactly the functionality we want, except our method will be scouring the model for a different attribute (Our ToolTipAttribute), what this means is we can use the exact same extension method signature for our own extension method.


The code inside this method is as follows


The first line of note is

var exp = (MemberExpression)expression.Body;

which basically extracts the Model and it's property name from the expression passed in.

Then the loop starts through that property's attributes until it finds either our new ToolTipAttribute or a Required attribute. It's completely up to you but I have written this in such a way that a ToolTip attribute will always override a Required attribute, but to get tool tips immediately up and running right throughout your site, you can use the Required attribute that should already be implemented all over your models. You can then fine tune later with your new ToolTip attribute. Hence why I put a required attribute on 'Position' before. Up to you really.

I have also created a helper method PerformMessageBuild() in this class that will return a piece of Html based on what it is given. This will add a dynamic class to the span element that is generated so we can target the span later with jQuery.


Build your project and that is it. Now you can use this in your view anywhere in your site like this.


VS2010 intellisense might not like your new statement at first but it does work and eventually it sorts itself out.

Running the app now should make no actual difference to the page as the span we have created was set to be hidden by default.

We can sort that with some jQuery so when you click in and out of the text boxes, our tool tip span is displayed, using our dynamic span classes.





And that should be it. You might want to style your tooltip to be standing out and maybe add some fancy fading animation or whatever. You also might want to expand on the jQuery to hide the tool tip message when the validation message is showing for that property, all this can be achieved quite easy by tweaking the jQuery.

You can download this sample here.
Please leave a comment if this was (or wasn't!) any use to anyone, along with any other thoughts.

Thanks
Jason

Thursday 26 May 2011

First One - Here goes

My first blog will be short and sweet(ish),

Over the past few years I have been lucky enough to work for companies who not only encourage learning and enhancing new development skills, but they pretty much demand it. Which in itself makes it much easier for a developer like me to be motivated to constantly pick up new skills, resources, languages and techniques and of course develop the mentality to be able to do this with enthusiasm. Not that I am a lazy person by nature of course :)

As I have come across some interesting bits and pieces, I have been encouraged by various colleagues to go down the road of blogging about them. These bits and pieces have mainly come in the form of Asp.Net MVC,.Net (C#), javascript/jQuery and more lately I have been getting involved in a lot more mobile web development including iPhone Application development via Monotouch (very interesting stuff). You might already know everything I have blogged about, which is fine, if not hopefully some of this will help, or might be of some interest at least!

I also might not limit this blog to software development and work, if I feel I can create an interesting topic to blog about, I will do so!

First (proper) one coming soon - Create a custom HtmlHelper method to allow very easy and simple tool tips on your MVC3 site - @Html.ToolTipFor(x => x.Name)

Any comments, tips or suggestions are more than welcome!