Thursday 12 July 2012

Into the world of website promotion

Since lawnching (see what I did there?) the lawn calendar application on Sunday 24th June, I've been in a mixture of support and intense learning mode.  Our content manager, Phil, has been busy adding new content to the site including tips and remnders, and in doing so, found our first bug which was promptly fixed and applied.  I've also patched in some minor additions such as a google +1 button and the google analytics hook.  This leads me neatly to the intense learning.

This application is my first live internet application, so I admit to being a complete beginner with regards to promoting a new site.  I knew it had something to do with search engine optimisation (SEO), but was pretty naive with regards to what that actually involved.  I stumbled upon a blog how to build a niche site which explains in quite some detail how the blog author and others achieved top 10 search engine rankings for their sites.  I probably learned something new with every sentence! I additionally found a whole host of resources that I previously didn't know that existed.  I think the key thing that I have learned is that it is very easy to spend a lot of time promoting a site, but if you get some of the fundamentals wrong, you will be wasting a lot of time and effort.  Much of the material that I have read make reference to the '4 golden rules', which once understood, do make a lot of sense.

The initial intention after launching the site was to get 'cracking' on V2 which would have features that allowed for personalisation of content.  However, I've taken the decision to spend some time working on another project whilst this application 'finds it's feet'.  I'll still keep posting blog post on here, as and when I discover something new.

Friday 22 June 2012

Going Live!

It's been a while since I last blogged on the subject of the Lawn Maintenance Calendar, now know simply as Lawn Calendar.  The plan is go live this Sunday.  Although things are pretty much ready, there are a couple of tasks that I need to complete.

Firstly, I need to create a 'down' screen that I can switch on whilst I upload and configure the site.
Secondly, I need to work how how the data migrations are going to work.  The content provider has already uploaded quite a bit of content into the system on the test hoster and I want to use that as the basis for the live database.  That way, the content provider can add images to the existing written content.  Entity framework now has a migration feature which might be just the replacement I need for the existing DropAndCreateOnModelChange strategy that is currently employed.

Update:  The launch went ahead on Sunday after a hive of activity on Saturday.

Down screen

I found that my new hoster already provides this function, so I didn't have to develop it myself this time.  It's not the most beautiful of down pages, but it will do for the time being. 

Data Migrations   

I've moved to using Entity Framework 4.3.1 which includes the migrations feature.  This now allows me to make database enhancements and upgrade without having to lose the contents of the database.  I've been very impressed with it and will be using it's scripting features to upgrade to V2 when the time comes.

Here's some useful links regarding EF 4.3. and migrations:
http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-automatic-migrations-walkthrough.aspx
http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx
http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-configuration-file-settings.aspx
http://www.ladislavmrnka.com/2012/03/ef-4-3-migrations-and-existing-database/

Uploading to hoster

This was quite straightforward for the website itself, but the database was a little trickier.  I couldn't find a way of uploading the mdf files and attaching them to the database like I could with the test site hoster. So, the only way I could get the database uploaded was to create an empty database, script and re-create the schema and then import the data using SSIS.

  

Wednesday 25 April 2012

Next phase

I've now completed the development for phase 1 of the Lawn Calendar.  It's now on the test server where we are going to leave it until we are ready to deploy to a full paid server.

Before we can fully go live, I want to set up the following:
  • www.lawncalendar.co.uk domain name for the site (registered).
  • A forum where users can discuss the application and suggest features and improvements.
  • Search engine optimisation (SEO) so that people can find the application from Google and Bing.
  • Facebook 'like' and Twitter 'tweet' buttons on the application (maybe)
  • Add legal disclaimer, t&c etc
Update:

Forum: now set up at freeforums

Some webpages with royalty free disclaimer, t&c examples:

http://www.businesslink.gov.uk/bdotg/action/layer?r.l1=1073861197&r.l2=1074448560&r.s=tl&topicId=1076141950
http://legal123.com.au/is-it-better-to-have-a-website-disclaimer-or-terms-and-conditions-on-my-website/

There was an issue with uploading images with upper case extensions.  Here's an article that talks about this:

http://forums.asp.net/t/1682158.aspx/1

Tuesday 24 April 2012

Merging LMC and Content manager

To hand over the LMC to the the testers, I needed to publish the application on a hosting server.  I found one that is free to host for 90 days (3 months).  Eventually, I'll upgrade to a paid service, but this free one will do for now.

One limitation of the free hosting service is that you can only install one application at a time.  The service is intended as an aid for students to learn ASP, so they don't want commercial applications.  So to get around this limitation, I needed to put the content management application in with the main LMC application, so that they shared the same web.config file.  I could then use custom routes to access the content manager.  I also needed a way of specifying different layouts for the LMC and the content manager.   

Here are a couple of links that helped out:

http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-custom-routes-cs
http://stackoverflow.com/questions/5161380/how-do-i-specify-different-layouts-in-the-asp-net-mvc-3-razor-viewstart-file


Once installed, I ran into the old UK vs US dates problem when trying to submit maintenance task data to the controllers.  Found this solution which creates a model binder to handle the date conversion.

http://stackoverflow.com/questions/9821407/mvc3-en-gb-dates-in-get

Sunday 1 April 2012

Date Filtering and Back to the weather API

I've been working on the LMC all weekend with the intention of finishing it off so I can start on another project next week while the stakeholder is away!

Date Filtering

Whist I was building out the Content Manager application, it dawned on me that I couldn't use the basic date range filtering that I had been using. The reason for this is that the content date ranges aren't actually date ranges because they do not have a year element. For example, one range might be 02/03 to 02/06 whereas anther may be 10/10 to 10/02 (i.e. go over a year boundary). The only thing I could assume is that a period would always be less than a year long.

So, once I had replaced the display and editor templates in the Content Manager to work with dd/mm entries. I had to revisit the LMC application and write some custom filtering logic to replace the basic date between logic.

Weather API

I'd been looking at weather widgets from various sources, and whilst they ware all very nice, none of them really ticked all the boxes for what I wanted. I had two main criteria. Firstly they need to be able to take a post code district as a parameter. Secondly, the size and styling of the widget had to fit in with the look and feel of the Lawn Maintenance Calendar style. The closest I got to finding a widget that worked was the Met Office one. It looked good on the site, but there was no way of dynamically sending through a post code district.

Initially, I'd played with World Weather Online's free weather API, which is a nice little rest service. But I stopped playing with it when I discovered the widgets because I didn't want to re-invent the wheel, so to speak. But I went back to the API in the end because it was the only solution that could match my acceptance criteria. It accepts a post code district as an input and because it just returns the data and image links as XML, I'm free to present it in any way I wish. This is great because I could use ASP.NET MVC display templates to lay out the forecast just like the widgets that I had been using (very MVC). I could then use the same styling that is used throughout the application to style the 'widget' so it looked like it was part of the rest of the app. I have to say, I'm very happy with the result.

The next thing I need to do was ask the user for the postcode district (the first part of the postcode). Initially, I was going to ask the user to register for an account and specify the postcode at the registration stage, but after having a good think about this, I decided to just use a cookie instead. I'll probably be adding user accounts at a later stage when I introduce personal notes to the calendar. For the time being, using cookies to capture and keep the postcode district works well.

So, I've now completed the development for the first phase of the Lawn Maintenance Calendar. I now need to get it tested by the content manager before putting it live.

Friday 30 March 2012

Building out the content manager

Just a quick post today. Just building out the content manager, so just pretty straightforward coding. Created a display template (which amounts to a special partial view) for dates so that the time part is omitted. I also needed to solve a problem were line breaks weren't being shown on multiline text. This was resolved with a simple replace call, but probably could be done more elegantly with a display template. Earlier on, fixed a few niggles with the calendar app, such as the selected date resetting when going to the about screen or keyword detail screen. Did some general tidying of these screens.

Thursday 29 March 2012

Conflicting jquery script file references

I've had this intermittent problem with the accordion control. Every so often, when the div that backs the accordion is loaded, the accordion style is not applied and I'm left with just a h3 and a div. Yesterday I switched all the jquery script references to hosted which improved the rendering performance, but has now introduced this issue. To solve it, I removed the references that I had placed in my partial page razor files. I'd put these in initially to get intellisence to work, but it seems that you cannot have the same reference in the _Layout.cshtml and in the partial page files. I'll have to do some internet digging to see if this is a known issue.

On a more fun note, I used the very impressive ASP.NET MVC scaffolding wizard to quickly create a content management application for the Lawn Maintenance Calendar. All I had to do was re-use the code first model classes that I had created for the LMC and context class and the wizard went away and pretty much created everything; controllers and views for index, create, edit, details and delete. I had to make a few tweaks here and there and add in the role security to prevent non content managers accessing these controllers.

Now, I can understand that this approach of mass automated boiler plate code creation is not ideal for commercial quality production systems where every user story through the system should be test driven. Also the controllers had been coded up to make direct calls to the database context, which ideally should be abstracted to a data access layer. But I still couldn't help by being impressed with the way it created the views and controllers, even if you do end up throwing away much of the code.

Wednesday 28 March 2012

Test Deployment to IIS

Up until now I've been testing the application through visual studio's built in web app host. I thought now would be a good time to attempt a deployment to the local IIS instance. I used visual studio's publish feature to get it installed. As the project is a web application as opposed to a web site, I needed to check a box to 'Mark as IIS application on destination'. This also has the effect of adding the application to the Default App Pool.

There were a few other things that I needed to do to get the application running. Firstly I had to change the app pool to run under .NET framework 4. Secondly I had to set up IIS APPPOOL\DefaultAppPool to have read/write access to the development database for the project. I'll set up a special test database for this later.

Once I got these things set up, I could run the application, but there were some issues with some resources not being found. These fell into the following categories:
  • File was set as BuildAction - None, so didn't get deployed
  • Controller action not found. This was fixed by using Url.Action helper to generate the url rather than use a relative path.
  • JS and CSS not being picked up. This was fixed by using Url.Content to generate the url rather than use a root based path.

Dynamic Detail Links

To dynamically inject the detail links from the task content to the keyword detail content I decided to inject the links using Regex.Replace, just prior to displaying the task content. So I wrote a helper that the razor page could call to make the replacements.

For this to work, I needed each task to have a property that contained a list of keywords that were applicable to the content, so I could pass these into the helper method. I didn't want to store these keywords with the task, as then I'd need a housekeeping task to keep these lists up to date with the detail content.

So, I used LINQ to SQL to dynamically look up keywords that were found in the content, which I then added to my new property. To prevent the new property from being automatically added to the task table, Entity Framework allows you to annotate properties on your entity classes as NotMapped. This is basically saying I'm going to calculate the values for this property myself in code.

To verify that EF was making the queries that I was expecting, I used a SQL profiler. I could see that the correct queries were being made and that SQL Server was correctly caching queries that had already been run.

Note about XSS: I've been reading up about cross site scripting (xss) and how pages can be vulnerable to such an attack if content containing html elements are not html encoded prior to display.

In this solution, I'm injecting links into content and for the links to be displayed correctly in the browser, I'm bypassing html encoding of the content using @Html.Raw. So to prevent a vulnerability, my helper method pre html encodes the content before injecting the links. This way, only the links that are injected by my managed code will reach the browser as html.

The other thing that I will need to do, before deployment, is ensure that the assembly containing the helper is signed with a strong name to prevent switching of a malicious version.

Tuesday 27 March 2012

Back-end

To get the back end in place, I introduced two new technologies.

Firstly, I introduced Unity as my dependency injection (IoC) container. This means that I can couple the controller, service and data access layers of the application at run time through dependency injection. As the controller instance is created by the MVC 3 framework, I needed a way of telling MVC to use my unity container. After some internet digging I found that the MVC framework provides an interface that can be used as an adapter for the Unity container. All I had to to was wrap the Unity container exposing the IDependencyResolver interface and then set the resolver in MVC using DependencyResolver.SetResolver. Quite a neat solution I thought.

Secondly, I introduced an entity framework code-first context. I had already used code-first on another project and was very impressed. Using the plain old CLR object (POCO) classes that I had created when designing the front end, I could generate a database, seed it with data and read back data using a LINQ to SQL statement. This all seems like quite a lot of work, but it was remarkably straightforward. The only thing that I needed to do to the POCO class was add a property to represent the primary key (public int id { get; set; }).

The data seeding is done by creating a class that inherits from DropCreateDatabaseIfModelChanges. So each time the application starts, this will check for changes and rebuild and reseed the database if required.

Well, we are almost done for the core of this application. The next piece of work will be adding detail links to keywords in the maintenance task content. I'm going to need to have a little think about how I'm going to achieve this. All I know is that it will involve dynamically adding in links to the content at some point.

Sunday 25 March 2012

Date Picker

To replace the Telerik calendar control with the jquery-ui inline date picker, I've had to get familiar with jquery and AJAX. When selecting a date, I wanted to make a post-back to the server so that I could fetch the maintenance tasks to display on the right hand side.

With the Telerik calendar, this was easy, as the control has an action method that allowed me to invoke the controller. The only difficulty I had was with a bug in the control which prevented me from changing the date format to a non localised format. I found this solution: http://www.telerik.com/community/forums/aspnet-mvc/calendar/calendar-date-format.aspx

Anyway, back to the jquery-ui inline datepicker. To do the callback to the controller, I needed to hook up a client side event handler (onSelect) and get it to make an AJAX call. I then had to modify my controller action so that it returned either a full view when called outside AJAX (i.e. for when the whole view is loaded on initial routing) and a partial view for when it's called from AJAX. Another handler receives the partial view and inserts the partial view into the relevant div.

This approach is great for 2 reasons: Firstly, the whole page doesn't get refreshed each time the date is changed, just the contents part of the page that needs changing. This also means that I don't have to send the date back to the view to keep the state on the date picker.

Now I'm reasonably happy with the UI, I'm going to start building out the back end of the application. I want to be able see maintenance tasks from the database. Whilst I was working with the UI, I was happy to use some 'canned' data from in-memory entity objects.

NB: I found quite a good site that explains the basic web concepts with lots of examples. This has been very useful to me when delving into javascript, html dom and jquery:
http://www.w3schools.com/default.asp

Friday 23 March 2012

Accordion

Today I've been dipping my toes into the world of jquery-ui. I wanted a collapsible panel, but found that the Telerik one needed to be bound to a collection-master-detail type model setup. What I was after was a collapsible panel that would bind to collection-title-content type model. I found that the jquery-ui accordion offered such a feature.

It took me a while to get the accordion up an running, mostly because the jquery scripts used by the Telerik calendar component was interfering with the jquery-ui scripts.

I'm now looking into using the jquery-ui date-picker to replace the telerik calendar component. This will offer an unified look and feel with the accordion. I need to work out what client side scripting is needed to invoke the action method on the controller and then read back the selected date.

Thursday 22 March 2012

Mowing Lawns

I'm a big believer in learning new skills by doing for real. So, when I asked my family members if they could think of a software application that they would use on a regular basis, it was my intention to develop these applications and see them go live.

One of these ideas came from my father. He's recently decided to start a lawn maintenance business and wanted an application that would remind him what jobs needed doing around the year to maintain a lawn. The idea was that this could be a web application that anyone could use.

This project will involve a couple of firsts for me:

Firstly, I have never developed an Internet hosted web application before. the nearest I have got to this is developing various intranet applications. So, I'm expecting a learning curve in the areas of user management and scalability and security. I'll also be procuring a domain and hosting for the first time.

Secondly, I'll be developing the application using C# and the ASP.NET MVC web application platform. So, again, I'm expecting a steep learning curve in the areas of URL routing, client side JavaScript, AJAX. All my previous web application development experience is confined to the world of ASP.NET (WebForms).

So here, I will try to document the journey from idea conception to going live and beyond.