Browse by Tags

All Tags » embedded javascript   (RSS)

My first day of MIX was an exciting one. I expected the keynote would cover the non-Silverlight and Windows Phone 7 topics so contrary to the reports of "oh no" you'll invariably hear, it only served to stretch my own excitement as I look forward to today's keynote and what it will have to offer. I already reported on the keynote, so I thought I'd share a bit about sessions.

The first session I attended was HTML5 for Silverlight Developers. It was very eye-opening to me. The speaker had experience on both the Silverlight product teams for earlier versions and the phone, as well as more recent tooling for HTML5 so he spoke from a position of authority. It turns out there are far more similarities between the two than I expected. The comparison, however, also served to draw out the fact we'll hear time and time again: the lack of good tooling for HTML5.

The most interesting part for me was when he designed a full path in Expression Blend, then took the path expression and pasted it into SVG and demonstrated the same drawing in HTML5. That was very interesting, as well as some tools and plug-ins that would generate the code from existing products. He also provided a large chart comparing features between the two ... for example, SVG mapping to XAML, Timer vs. DispatcherTimer, etc. I enjoyed the session and learned quite a bit.

My next session was a Deep Dive MVVM with Laurent Bugnion. Laurent did a great job because there was a ton of information to pack into only a very short window of time. While there were some things I didn't necessarily agree 100% with on the approach, the point wasn't about a debate around "what's the pure or right way" but instead, "here is your tool box and these are the challenges people claim to face, so here's a way to solve them." In that sense I think the talk drove home that you cannot overcomplicate matters and sometimes it's OK to have a little code behind (yes, his demo had code behind!) He managed to hit most of the questions people tend to ask about MVVM with a solution within the framework.

The final session was Pragmatic JavaScript, jQuery, and AJAX with ASP.NET. It was again a very informative session. I learned new ways the Microsoft tools support jQuery and even help provide support for extensions, intellisense, and more. He also tackled some various challenges you might face such as long-polling and how to resolve it using the combination of jQuery and the ASP.NET tools. At the end of the meeting I felt like the open web (meaning tags and JavaScript) looks very fun again and I want to get more involved with it in addition to Silverlight.

As fun as that day was, I know this day will be even more exciting. Stay tuned on my twitter feed (@JeremyLikness) as I report from the keynote floor for what I expect to be some amazing announcements in the Silverlight and Windows Phone 7 space.

#msmix11sw

Jeremy Likness

Silverlight, with its powerful text and graphics manipulation capabilities and strong interaction with the scripting DOM, seems to be the perfect engine for a Captcha challenge.

See an Example Online

Download the Source (18.3KB)

Captcha is a challenge-response test used to determine to a degree of confidence that the end user is really human and not a bot. You see Captcha on things like forums, sign up forms, comment posts, and other places that may be succeptible to attacks by scripted bots. Usually, a Captcha involves playing a sound or displaying a distorted image that humans should be able to recognize but would be extremely hard for pattern-matching and/or optical character recognition (OCR) technology to decipher. Because the test is issued by a computer to test for a human, it is often referred to as a reverse-Turing test (a Turing test is designed by humans to test computers).

The key to Captcha is that it makes it difficult, if not impossible, for scripted software to determine the answer to the challenge. Asirra is an example of a Captcha challenge that displays random images of cats and dogs. The user is asked to identify only the cats by clicking on them. While easy for humans, this test is extremely difficult for computer algorithms.

As I was coding the other day, it occurred to me that Silverlight would be perfect for issuing Captcha challenges. It is very easy and straightforward to manipulate text and graphics to obscure the image, and furthermore, the output is NOT a simple bitmap that a robot could parse. Instead, it is an interactive plugin so for a script to recognize the image, it would have to have its own Silverlight engine and be able to scan and recognize what Silverlight renders.

I set out to produce a working example. I purposefully kept to the basics so those of you reading this who are interested have the opportunity to extend and add features.

The first step was to create a simple Captcha challenge class to use.

namespace SilverCaptcha.MVVM
{
    [ScriptableType]
    public class CaptchaViewModel
    {
        private const string CAPTCHA_KEY = "SilverCaptcha";

        private static readonly char[] _charArray = "ABCEFGHJKLMNPRSTUVWXYZ2346789".ToCharArray();

        public string CaptchaText { get; set; }

        public CaptchaViewModel()
        {
            char[] captcha = new char[8];

            Random random = new Random();

            for (int x = 0; x 

The class simply generates a random 8-digit sequence of characters. We supply a list of allowed values to avoid some of the common characters like the number one and letter "I" that could be easily mistaken for one or the other. The property CaptchaText exposes this value. The IsHuman method is decorated with the ScriptableMember tag. This makes it available to the Html DOM so that you can call it directly from JavaScript. To call it, you must register a "key" or handle to the object. This is done in the constructor through the RegisterScriptableObject call. We are giving it a handle in the JavaScript DOM of "SilverCaptcha." We'll see later how this is used.

Points of Extension

  • Add a method to "refresh" the challenge, i.e. generate a new one (hint: to do this, you'll also need to implement INotifyPropertyChanged)
  • Add parameters to control the challenge (length, use of alpha or numeric, etc)

Next, we'll need to show the challenge. Because I chose to use the Model-View-ViewModel pattern (MVVM) we won't need any code behind for the XAML. Instead, everything will be bound in the XAML itself. The XAML I came up with looks like this:

<UserControl x:Class="SilverCaptcha.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:MVVM="clr-namespace:SilverCaptcha.MVVM">
    <UserControl.Resources>
        <MVVM:CaptchaViewModel x:Key="CaptchaVM"/>
    </UserControl.Resources>    
    <Grid Width="100" Height="25" Margin="2" DataContext="{StaticResource CaptchaVM}">
        <Grid.Background>
            <LinearGradientBrush x:Name="CaptchaBackground" EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="LightBlue" Offset="1" />
                <GradientStop Color="LightSalmon" />
            </LinearGradientBrush>
        </Grid.Background>
        <TextBlock FontSize="14" Width="Auto" Height="Auto" 
                   HorizontalAlignment="Center" VerticalAlignment="Center" 
                   Text="{Binding CaptchaText}"
                   RenderTransformOrigin="0.5,0.5"> 
            <TextBlock.RenderTransform>
               <RotateTransform Angle="-5"/>              
            </TextBlock.RenderTransform>
            <TextBlock.Foreground>
                <LinearGradientBrush EndPoint="0.5,0" 
                    StartPoint="0.5,1">
                    <GradientStop Color="Black" Offset="1" />
                <GradientStop Color="Gray" />
                </LinearGradientBrush>
                                    
            </TextBlock.Foreground>
        </TextBlock>
    </Grid>
</UserControl>

This is fairly straightforward. By referring to CaptchaViewModel in the resources, an instance is created that can then be referenced using the key. I bind the class to the data context of the main grid using {StaticResource CaptchaVM}. The gradient is used to obscure the image somewhat. Because the class itself is bound to the grid, we can now simply bind the CaptchaText property to the text block. We also give that a slight gradient to make it more confusing to image scanning software, then rotate it against the background. That's all there is to it!

Points of Extension

  • Obviously, you could randomize or parameterize the angle of rotation and other attributes of the text
  • A more severe grid may help obscure the challenge but may also make it more difficult for human readers
  • Add a refresh button or icon to refresh the challenge for the user

Now, let's use it in a page. The page itself is fairly straightforward: we have a form with a table, and inside the table is a reference to the Silverlight XAP file, a text box for the user to enter their response to the challenge, and a button to click. This section looks like this:

<form id="_form1" runat="server" style="height:100%">
    <table><tr><td align="center">
    <div id="silverlightControlHost">
        <object id="silverlightControl" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="110" height="30">
        ... etc, etc ...
     </object></div></td></tr><tr>
     <td align="center">Enter The Text You See Above:<br /><input type="text" maxlength="20" id="txtChallenge" /></td></tr><tr>
     <td align="center"><input type="button" onclick="validateCaptcha();return false;" value=" OK "/></td></tr></table>
    </form>

(Click here to see a live example)

The key here is that we've assigned the silverlight object an identifier of silverlightControl. If you use the Javascript or control method to load the silverlight, either way you just need a way to point to the object in the DOM for the Silverlight control.

The JavaScript function is then very straightforward. We simply call the method we exposed in the Silverlight class that will compare the response to the challenge. That code looks like this:

function validateCaptcha() {
    var silverlightCtrl = document.getElementById("silverlightControl");
    var challenge = document.getElementById("txtChallenge").value;
    var valid = silverlightCtrl.Content.SilverCaptcha.IsHuman(challenge);
    alert(valid ? "You are human!" : "You don't appear to be human, try again!");
}

This is what the final product looks like:

Captcha Challenge

As you can see, calling the Silverlight method is as simple as grabbing the control that hosts Silverlight, going into Content, then referencing the tag we gave it when we registered it in the Silverlight code. Then we simply call the method with the contents of the text box and it returns either true or false based on whether or not the response matches the challenge.

This is obviously a fast and basic example but it demonstrates just how flexible and powerful Silverlight can be to generate "mini-apps" or controls that you can embed in your existing HTML pages.

See an Example Online

Download the Source (18.3KB)

Jeremy Likness