Wednesday, 2 December 2009

YouTube, MS MVC and jQuery

In this entry I’m going to make a MS MVC PartialView (usercontrol) which will take in a search term and render a YouTube video down to the page.

You can see how this will look on TV Shout, where I’ve used it to display film trailers on the listing pages of films.

You should be able to drop the code into your MVC project and instantly get some YouTube integration on your website.

If you want you can grab the code for the tutorial here.



The Google Data API

First up we’re going to need some references to the Google Data API.

“The Data API allows a program to perform many of the operations available on the YouTube website. It is possible to search for videos, retrieve standard feeds, and see related content. A program can also authenticate as a user to upload videos, modify user playlists, and more.”

We’re going to keep it simple here, and just use the API to query YouTube to look up videos.

Grab the .Net API Library from Google code. We need to add references in our project to:

Google.GData.Client.dll
Google.GData.Extensions.dll


The Controller and Search Code

Create a function in your controller (not the best place for it, but for brevity...) called GetFeed. This method will run off to YouTube and return an AtomFeed with a specified number matching videos:
Private Shared Function GetFeed(ByVal url As String, ByVal start As Integer, ByVal number As Integer) As Google.GData.Client.AtomFeed
Dim query As New FeedQuery("")
Dim service As New Service("youtube", "exampleCo")
query.Uri = New Uri(url)
query.StartIndex = start
query.Query = Replace(query.Query, "%20", " ")
query.NumberToRetrieve = number

Dim myFeed As Google.GData.Client.AtomFeed = service.Query(query)
Return myFeed
End Function



Next, we need to add the controller function which will return a PartialViewResult. We will be hitting this function via an AJAX call from the client web page, and it will be sending back the HTML to our page required for displaying the video player.

Public Function YouTubeVideo(ByVal searchTerm As String) As PartialViewResult
Dim url = "http://gdata.youtube.com/feeds/videos?q=" + searchTerm
Dim myFeed = GetFeed(url, 1, 1)
Dim idSimple = ""
If myFeed.Entries.Count > 0 Then
' We just need the unique ID of the video - grab it from the unique URI
Dim uriSection() = myFeed.Entries(0).Id.Uri.ToString.Split("/")
idSimple = uriSection(uriSection.Count - 1)
End If

Return PartialView("YouTubeVideo", idSimple)
End Function




The Views

Next up we need to add a PartialView for the video mark-up. Add a user control to your page. We want to set the Model of this user control to be of type string:
<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of String)" %>
<% If Not Model = "" Then %>
<div id="video">
<object width="540" height="444">
<param name="movie" value="http://www.youtube.com/v/<%=Model %>?color1=0xb1b1b1&color2=0xcfcfcf&hl=en&feature=player_embedded&fs=1">
<param name="allowFullScreen" value="true">
<param name="allowScriptAccess" value="always">
<embed src="http://www.youtube.com/v/<%=Model %>?hl=en&feature=player_embedded&fs=1"
type="application/x-shockwave-flash" allowfullscreen="true"
allowScriptAccess="always" width="540" height="444">
</object>
</div>
<% End If%>



In this user control, we will set the Model to the Unique ID of the YouTube Video. This value will then be injected into a YouTube URL creating something similar to the following:

http://www.youtube.com/v/WhBoR_tgXCI

(May as well watch the above video whilst you’re reading the rest of this... DubFX is heavy, I’m sure you’ll agree)


Showing a video on your page

We are now at the stage that your shiny new YouTube user control can be used in your web app.
We just need to create an AJAX call from the particular view we want to place the video in, to our controller method : YouTubeVideo()

Add a link to jQuery in the Head of your view (as if you haven’t got one there already) and a div to place the video in.


Next up we add the jQuery script to call the
<script type="text/javascript">
$(document).ready(function() {
$.get('/[[YourControllerName]]/YouTubeVideo?SearchTerm=[[YourSearchTerm]],
function(data) {
$('#youtubeVid').html(data);
return false;
});
});

</script>



And that’s you done. YouTube videos integrated!

The code here is simplified and could probably do with some tidying up if you want to use it in a production system.



kick it on DotNetKicks.com

Tuesday, 17 November 2009

Fancy validation pointer messages without images

Here's a neat little CSS trick that allows you to create validation messages which point to the relevant field without the use of images.


It basically makes use of the CSS border property to make pure CSS shapes. In this case, we make a triangle connected to a rectangle giving you a pleasant arrow shape in which to hold your validation message.


Here's what the effect looks like:

And here's some mark-up for you:


.valPointer {
border-color: transparent #e9e9e9 transparent transparent;
border-style: solid;
border-width: 14px 14px 14px 0px;
height: 0px;
width: 0px;
float: left;
}

.valBody {
background: #e9e9e9;
float: left;
height: 28px;
width: 146px;
font: normal 11px arial;
padding: 0 2px 0 5px;
}

<div id="errorArrow" >
<span class="valPointer"></span>
<span class="valBody">This is mandatory. Please enter a value.</span>
</div>




Good little trick and saves you busting Photoshop open. What do you think? Useful? Would you use it?


Thanks to ChrisM for doing some research on this one for me!



kick it on DotNetKicks.com

Monday, 26 October 2009

Creating separate views to target mobile devices in MS MVC

This is a small how-to on creating separate view files to target mobile phones in your MS MVC websites. By the end of the article, I will have shown how to create new directories within your view folders which target various mobile devices. The views make use of the same controller files to deliver content to specific devices.

The Mobile Device Browser File

First up, I am going to add the Mobile Device Browser file to my project:

Project Description
The Mobile Browser Definition File contains definitions for individual mobile devices and browsers. At run time, ASP.NET uses the information in the request header to determine what type of device/browser has made the request.

This open source file takes care of doing the work of figuring out what kind of device is accessing the website. It allows you to target many different mobile devices, and takes out a lot of the hard work of for targeting specific devices.

To add the Mobile Device Browser File to your project, right click on your website project file in VS, and

Add > Add ASP.NET Folder > App_Browsers

Create another folder insider App_Browsers called devices

Drop the mobile.browser file from the Mobile Device Browser File Download in the newly created devices directory.

Using this file I can target the devices I want to support without having to know the specifics of what those devices send in their headers. I can just use the Request.Browser property to tailor which view I want to return.

Now I am going to put together the directory structure I will be using to target different devices. I have decided to use the following directory structure within my views section:

· Home

· Mobile

o iPhone

§ Index.aspx

o BlackBerry

§ Index.aspx

o Index.aspx

· Index.aspx

Basically, a standard request from a desktop computer will be served up the Home > index.aspx file. A request from an iPhone will be served up Home > Mobile > iPhone > Index.aspx.

A mobile device which does not have a specific directory in the mobile directory will be served the Home > Mobile > index.aspx view.

The Custom View Engine

Next up we are going to create a Custom View Engine, to override the standard MVC view Engine.

Our custom view engine will take care of routing request from mobile devices to the correct views.

Public Class CustomViewEngine

Inherits WebFormViewEngine

Public Overloads Overrides Function FindView(ByVal controllerContext As ControllerContext, ByVal viewName As String, ByVal masterName As String, ByVal useCache As Boolean) As ViewEngineResult

' Logic for finding views in your project using your strategy for organizing your views under the Views folder.

Dim result As ViewEngineResult = Nothing

Dim request = controllerContext.HttpContext.Request

' iPhone Detection

If request.UserAgent.IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) > 0 Then

result = MyBase.FindView(controllerContext, "Mobile/iPhone/" & viewName, masterName, useCache)

End If

' Blackberry Detection

If request.UserAgent.IndexOf("BlackBerry", StringComparison.OrdinalIgnoreCase) > 0 Then

result = MyBase.FindView(controllerContext, "Mobile/BlackBerry/" & viewName, masterName, useCache)

End If

' Default Mobile

If request.Browser.IsMobileDevice Then

result = MyBase.FindView(controllerContext, "Mobile/" & viewName, masterName, useCache)

End If

' Desktop

If result Is Nothing OrElse result.View Is Nothing Then

result = MyBase.FindView(controllerContext, viewName, masterName, useCache)

End If

Return result

End Function

End Class

Applying the Custom ViewEngine

Now that I have my Mobile View folders and mobile views created, and have implemented a Custom ViewEngine, I can go ahead and apply the custom view engine.

To do this we’ll need to clear any existing ViewEngines and add a new instance of the ‘CustomViewEngine”. This needs to be done within the Application_Start method in the Global.asax.

' Replace the Default WebFormViewEngine with CustomViewEngine

System.Web.Mvc.ViewEngines.Engines.Clear()

System.Web.Mvc.ViewEngines.Engines.Add(New CustomViewEngine())

And we're done!

That's everything you need to do... Hit the site with your mobile phone, and IIS will serve up your customised mobile views. Got to love the MS MVC Framework!


This post was inspired by a stackoverflow answer given by Dale Ragan. Cheers Dale!


kick it on DotNetKicks.com

Monday, 12 October 2009

Draggable scrolling list with jQuery

DraggableList is a jquery plugin for making a list or other html element scroll within a draggable container.

Check out a demo here

Simply point the pluggin at an unordered list (or other element), specify a containment size and the list will become draggable. Drag the list up and down to scroll its contents.

Example Usage


<style type="text/css">
body{ font-family:Georgia;}
.myList {list-style:none; margin:0px; padding:0px;}
.myList li{ height:50px; border-bottom:solid 1px #dedede; margin:0px; padding:0px 2px 0 2px;}
.draggableList{ border:solid 1px black;}
</style>

<script type="text/javascript">
$(document).ready(function() {
$('.myList').draggableList({height:150, listPosition:0});
});
</script>

<ul class="myList">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>


Options

The plugin has a bunch of options with default values as follows:

        cursor: 'n-resize',
height
: '150',
width
: '100',
listPosition
: '0',
panelCssClass
:'draggableList'

cursor

CSS cursor style on hovering over the list

height

Numeric-value - pixels The height of the element which will hold the list (it's overflow will be set to hidden)

width

Numeric-value - pixels The width of the element which will hold the list

listPosition

Value between 0 and 100 : Where abouts the list will be positioned relative to it's container. When 0, the list will appear scrolled right to the top, so the first element will be at the top of the container. When set to 100 the list will be scrolled right to the bottom

panelCssClass

Name of the css class that is added to the container item. Used to style the container.

Dependancies

DraggableList dependancies on:

Source

Head across to http://code.google.com/p/draggablelist/ and grab the plugin now.

And if anyone uses the list on one of their projects, I'd love to hear about it and get feedback on how it could be improved...




kick it on DotNetKicks.com

Wednesday, 9 September 2009

Cruise control with MSBuild - Switching a reference on the build server

Background

This article is the result of the following problem I encountered a few days ago: We have a piece of software which references a third party dll. We had to deploy the software to a customer with a 64bit server.

This isn’t a problem for the code written in house, as it is all managed so runs in a 64bit environment no problem. Unfortunately, the third party dll we are using is 32 bit specific. There is a 64 bit version, but in order to develop against the library we have to reference the 32 bit dll (we all work on 32 bit machines).

The build setup

First off, we keep all third party dlls within a folder in our solution, so anyone can grab the source code from VSS (I know...) and compile it.

We run Continuous Integration using Cruise Control and MSBuild to do the building by reading our solutions files. On every check-in, a build is triggered, resulting in a build containing everything the software needs, ready to deploy.

Fixing the problem

First we deployed the software to a 64 bit server and tried simply copying over the 32 bit dll with the 64 bit version – they are both the same version number, so with fingers crossed we fired up the app. No such luck:

The located assembly's manifest definition does not match the assembly reference

Kind of expected that to be honest...

We then restructured our external references folder ‘BinRefs’ a little, and added the 64 bit dlls to the solution:

Then changed the reference in the project file to point to the new location for the 32 bit dll.

The plan was to get the build server to open the project file containing the reference to the 32 bit dll and change the path to the dll so it points at the 64 bit version before building the solution.

VS2008 project files hold their references to dlls as below:

So I simply needed to replace the string

“..\..\BinRefs\32Bit\SomeLibrary.dll”

With the relative path to the 64 bit dll

“..\..\BinRefs\64Bit\SomeLibrary.dll”

Before MSBuild starts compiling.

A quick and dirty VBScript with a batch file to kick it off takes care of the job of replacing the HintPath in the project file:

VBScript (Replace32bitDLL.vbs)

dim fso
dim txtStr
dim strHolder
dim strFileToFix

' Replace reference to SomLibrary in MyProject project
strFileToFix = "Build64\Services\PDF\MyProject.vbproj"
set fso = wscript.createobject("scripting.filesystemobject")
set txtStr = fso.opentextfile(strFileToFix,1,false,0)
strHolder = txtstr.readall
txtStr.close
set txtStr = nothing
strHolder = replace(strHolder,"..\..\BinRefs\32Bit\SomeLibrary.dll","..\..\BinRefs\64Bit\SomeLibrary.dll",1,-1,vbtextcompare)

set txtStr = fso.createtextfile(strFileToFix,true,false)
txtStr.write(strHolder)
txtStr.close
set txtStr = nothing


Batch Script (Replace32bitDLL.cmd)

ECHO StartingDllReplace
CScript Replace32bitDll.vbs
ECHO FinishedDllReplace


Finally a task is added to the project section in the Cruise Control config file before the call to MSBuild (shown in bold):


<tasks>
<exec>
<baseDirectory>E:\Dev\Development</baseDirectory>
<executable>Replace32bitDLL.cmd</executable>
</exec>

<msbuild>
&msb3Exe;
<workingDirectory>E:\Development\Build64</workingDirectory>
<projectFile>MySolution.sln</projectFile>
&releaseBuildArgs;
<targets>Build</targets>
&msBuildLogger;
</msbuild>
</tasks>


And you’re sorted. Check-ins result in builds ready to be deployed to 64 bit machines.

Announcing TellyFeed - Beta Release

TellyFeed - Never miss another film when it's on TV!

What it’s all about?

TellyFeed was a little idea that came from a FaceBook app I built a couple of years ago to learn about the FaceBook api.

The idea came about as a way to find out when films were gonna be on tv (which is pretty much all I personally use it for) and it seems to do a relatively good job.

Basically, you enter a list of film or TV programme titles and TellyFeed can let you know if they’re gonna be on TV over the next 5 or so days. Fairly handy if you’ve got a fancy TV recording Freeview box and want to build up a little film collection.

Just hook up your RSS reader and you’ll never miss that film you’ve been meaning to watch.

So why did I build it?

I just finished reading Evans’ Domain Driven Design and decided that if I wanted it to sink in, I should probably try it all out.

I built the application basically as a controlled experiment... It’s a fairly simple application with a few business rules and concerns. I knew exactly what I wanted it to do, so I could sort of play the role of developer and domain expert.

I learnt a lot (Dependency Injection, the Repository Pattern, A fair bit more knowledge of the MVC framework, a good old bit about domain modelling, a bit about nHibernate, SubSonic SimpleRepository and quite probably a lot more.) which is good.

I'll be adding some blog posts over the coming weeks outlining some of the things I learned, and how I went about achieving some of the functionality on the site, so stay tuned!

Enjoy the site I hope you find it useful.

Monday, 27 July 2009

Using a windows service to schedule a job in VB.Net

A quick rundown on how to schedule a job from a windows service in VB.Net using the Quartz.net scheduling library. You may need to schedule a job to run for all sorts of reasons:

• Closing down old website sessions in a database
• Running a nightly refresh of data
• Pull files down from the internet

Or a million other things that I won't list here.

Depending on your level access to the server / your server policy, you may be able to tackle this task using a variety of other methods like scheduled tasks or, particularly pertinent if you are in a shared hosting environment, using IIS Cache expiry as a cheap way to schedule tasks.

A bit of background on Quartz

"Quartz.NET is a port of very propular open source Java job scheduling framework, Quartz. This project owes very much to original Java project, it's father James House and the project contributors.

Quartz.NET is a pure .NET library written in C# which currently targets Framework version 1.1 and above. Quartz.NET is feature-wise equal to Quartz Java 1.6 excluding Java specifics. Quartz.NET is already running in production systems and has received good feedback."

Some Code

The following example is some code I created to run a refresh job on some data:

First off, create a windows service project.

Add a reference to the Quartz library, which can be downloaded at http://quartznet.sourceforge.net/

At the top of your file add the import statements to the namespaces we will be using:

Imports Quartz
Imports Quartz.Impl

Now, in the service OnStart event of your service, add the following code:

' construct a scheduler factory
Dim schedFact As ISchedulerFactory = New StdSchedulerFactory()

' get a scheduler
Dim sched As IScheduler = schedFact.GetScheduler()
sched.Start()

' construct job info
Dim jobDetail As New JobDetail("RefreshJob", Nothing, GetType(Refreshjob))


Dim trigger As Trigger = TriggerUtils.MakeDailyTrigger(10, 30)


trigger.StartTimeUtc = DateTime.UtcNow

trigger.Name = "RefreshTrigger"
sched.ScheduleJob(jobDetail, trigger)


The above code has basically set up a scheduler, which, when triggered (by the time hitting 10:30) will look for a type (in this case RefreshJob) and run the execute method within the class.

So now we have to create the RefreshJob type, which will implement the interface Quartz.IJob

Imports Quartz

Public Class Refreshjob
Implements IJob

Public Sub New()
End Sub

Public Sub Execute1(ByVal context As Quartz.JobExecutionContext) Implements Quartz.IJob.Execute

' Run your code

End Sub

End Class


Conclusion


Really nice library, easy to use, Job's a good 'un.

For more functionality, check out the Quartz docs and examples at http://quartznet.sourceforge.net/





kick it on DotNetKicks.com


Thursday, 14 May 2009

XSRF - Thoughts on mitigation...

Having successfully manipulated a shopping cart in an unrealistic little test using a bit of jQuery and a simple Cross Site Request Forgery, it's time to discuss some of things we can do to avoid these sorts of problems in our own web applications.

The simple things

Use get and post correctly:

GET
Requests a representation of the specified resource. Note that GET should not be used for operations that cause side-effects, such as using it for taking actions in web applications. One reason for this is that GET may be used arbitrarily by robots or crawlers, which should not need to consider the side effects that a request should cause.

POST
Submits data to be processed (e.g., from an HTML form) to the identified resource. The data is included in the body of the request. This may result in the creation of a new resource or the updates of existing resources or both.
From wikipedia...

I figure it's best to just do what HTTP tells me to do on this one, and not think about it for too long.


Validate all your user input


Everyone has heard it all before, no doubt, but validate all user input on the server. If you're using MS MVC, check out xVal... Useful for wiring up client-side validation from your model. If you're using web forms, do whatever you have to do, but make sure you validate.


Store your user_id in the session


And accept as few details from the user as needed. You already know how much your product costs... you don't need the user to tell you.


Check the referrer


Check the referrer and ensure the request came from your domain. If you're using MS MVC, check out this post about the AntiForgeryToken.




Anyone got any other simple things we should be doing on this one?

XSRF Attacks in AJAX enabled apps

So, I've been doing a lot of AJAX development recently and decided to have a little think about the security the various methods and techniques that I've been employing...


The basic AJAX situation...

You have a button on your page. On clicking the button, an XMLHTTPRequest is made to a URL to perform an action. The action is executed and the web page receives some sort of response to say whether the action was successful... It may also supply some data to display on the web page - perhaps a JSON object, or maybe a chunk of HTML.


The thing I was particularly interested in was the security around the URLs that the AJAX request hit... Essentially, these URLs are simply open points to execute actions against your application.

In my apps, you have to be logged in to perform any action that changes data in any way, so a user would have to be authenticated in order for these exposed URLs to be abused.

As I write this, I have multiple tabs open in my browser (IE at the moment incidentally). One of the tabs is logged into my webmail account. I still have [MySuperMarket].com open where I'm in the middle of putting together my weekly food shop. I have iGoogle open in another, my blog is open and logged in, the current tab I am looking at, and finally a couple of wikipedia articles in some more tabs.

This means I am currently authenticated against no less than 4 web apps, without taking into account any sites I have persistent log in enabled on (that check box that asks if you want to stay signed in on this computer)... God knows how many of them I have.

So, I have established that at least 4 sites currently trust any requests sent from my browser.

My thinking followed the idea that any request from my browser - regardless which tab, would be able to execute actions against any of these logged in applications. Time to try and execute some actions in one of these apps from outside of it's domain then...


A Proof of concept...

I went to the tab with the supermarket site open. Opened fiddler, and hit a button to add some cooked chicken to my shopping cart:



The highlighted row above shows a call has been made to the url:

/basket/add.aspx

along with a bunch of querystring parameters (detailing the ID of the particular product, the quantity, and various other things).

I then removed the chicken from my cart.


Crafting the web page to abuse this action

I figured, all I would need is a webpage that creates an XMLHTTPRequest to the above url, with appropriate querystring data supplied. I created the following HTML file:



Hopefully you can see it is a basic page with a hyperlink. I have used jQuery to attach a click event to the hyperlink which fires an AJAX request to the relevant URL.

I opened the HTML page in my browser, clicked the link, went to the supermarket tab and refreshed my cart... Hey presto - There's some chicken in there.

It appears all I have to do is get people to follow a link to the HTML page I have created, and, if they are logged into the particular supermarket, everyone will be getting extra chicken with their shopping orders

<evilThoughts>
Ha ha ha. Today unwanted chicken chaos, tomorrow the world.
</evilThoughts>


Thoughts

This is obviously a bit of a silly little example, but is good for a POC. Potentially I could be performing all sorts of undesirable action.

Furthermore, what does this mean for online banking sites, betting sites or other places where money can be moved around?

At first consideration, this appears to be a fairly serious problem. It's known as a cross site request forgery or XSRF.

Whilst it doesn't just effect AJAX apps, I think that as people start to embrace AJAX it will be easy to make mistakes, unless we think carefully about exactly what functionality we are providing to the world at large - intentionally or not.

Further musings on this coming later...


kick it on DotNetKicks.com