Feed Icon  

Contact

  • Bryant Likes
  • Send mail to the author(s) E-mail
  • twitter
  • View Bryant Likes's profile on LinkedIn
  • del.icio.us
Get Microsoft Silverlight
by clicking "Install Microsoft Silverlight" you accept the
Silverlight license agreement

Hosting By

Hot Topics

Tags

Open Source Projects

Archives

Ads

Idle Timeouts in RIA Services Authentication

Posted in RiaServices | Silverlight at Wednesday, October 28, 2009 10:02 AM Pacific Standard Time

A question came up in the Silverlight Forums about how to timeout a user when using .NET RIA Services. Since I have implemented this before I thought I would share an approach I used. There might be a better way that is more integrated with the ASP.Net security, but for now this works.

To start with, you’ll need the Sample Application that Brad Abram has been building and blogging about and you might want to read through this post on Authentication in RIA Services before going any further. Once you have that and can build/run it on your machine you can continue on.

The security in Brad’s example uses a simple membership provider that is using RIA Services FormsAuthentication since it takes a username and password to log in. For our example we will extend the FormsAuthentication and add a timeout to it. Below is my implementation of the FormsWithTimeoutAuthentication class:

namespace MyApp
{
    public class FormsWithTimeoutAuthentication : FormsAuthentication
    {
        private DispatcherTimer idleTimer;
        private int minutesIdle;
        private bool idle;
        private bool attached = false;

        public FormsWithTimeoutAuthentication()
            : this(20)
        { }

        public FormsWithTimeoutAuthentication(int idleMinutes)
        {
            IdleMinutesBeforeTimeout = idleMinutes;
            idleTimer = new DispatcherTimer();
            idleTimer.Interval = TimeSpan.FromMinutes(1);
            idleTimer.Tick += new EventHandler(idleTimer_Tick);
        }

        public int IdleMinutesBeforeTimeout
        {
            get;
            set;
        }

        protected override LoginResult EndLogin(IAsyncResult asyncResult)
        {
            var result = base.EndLogin(asyncResult);

            if (result.LoginSuccess == true)
            {
                if (!attached) AttachEvents();
                minutesIdle = 0;
                idleTimer.Start();
            }

            return result;
        }

        protected override LogoutResult EndLogout(IAsyncResult asyncResult)
        {
            idleTimer.Stop();

            return base.EndLogout(asyncResult);
        }

        private void AttachEvents()
        {
            attached = true;
            Application.Current.RootVisual.MouseMove += new MouseEventHandler(RootVisual_MouseMove);
            Application.Current.RootVisual.KeyDown += new KeyEventHandler(RootVisual_KeyDown);
        }

        private void RootVisual_KeyDown(object sender, KeyEventArgs e)
        {
            idle = false;
        }

        private void RootVisual_MouseMove(object sender, MouseEventArgs e)
        {
            idle = false;
        }

        private void idleTimer_Tick(object sender, EventArgs e)
        {
            if (idle == true)
            {
                minutesIdle += idleTimer.Interval.Minutes;
                if (minutesIdle >= IdleMinutesBeforeTimeout)
                {
                    Logout();
                }
            }
            else
            {
                minutesIdle = 0;
            }
            idle = true;
        }
    }
}

All this class does is add a timer that fires once a minute. If the user has either moved the mouse or hit a key in that minute then they stay logged in. If the user hasn’t, then a minute of idle time is added to the idle minute count until the timeout limit is reached. Once that happens the user gets logged out.

Note that the events are attached to the root visual and don’t get attached until the user logs in. This is because the Authentication is created prior to the RootVisual being set.

Simply add this code to the sample project (linked above) and then change the authentication service in the App.xaml as follows:

<Application   
  x:Class="MyApp.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:app="clr-namespace:MyApp"
  xmlns:appsvc="clr-namespace:System.Windows.Ria.ApplicationServices;assembly=System.Windows.Ria"  
    >

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Assets/Styles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>


    <Application.ApplicationLifetimeObjects>
        <app:RiaContext>
            <app:RiaContext.Authentication>
                <app:FormsWithTimeoutAuthentication IdleMinutesBeforeTimeout="2"/>
                <!--<appsvc:WindowsAuthentication/>-->
            </app:RiaContext.Authentication>
        </app:RiaContext>
    </Application.ApplicationLifetimeObjects>

</Application>

Here I’ve set the IdleMinutesBeforeTimeout to 2 minutes so that it is easy to test.

Once you’ve modified the application, when you run it you will get logged out after the number of minutes you specify in the timeout. There are lots of enhancements that could be made to this simple approach, but this works for most situations.

Migrated from Community Server to DasBlog

Posted in Community Server | dasBlog | Sql and Xml at Saturday, October 17, 2009 8:30 AM Pacific Daylight Time

If you’re reading this then you’re on my new blog homepage at http://bryantlikes.com. I’ve wanted to move off of http://blogs.sqlxml.org for some time but every time I start to work on it I get overwhelmed by the amount of work involved. I would usually get stuck on (1) how to migrate all my content and (2) where to host it since there is a lot of content and most hosting providers give you very little SQL storage.

I looked at a lot of options and even setup Oxite on Azure by following this guide, but since I didn’t know what the monthly costs will be I decided not to take that route. Since I was recently awarded the MVP award I decided to look at some of the benefits and I found that Orcs Web offers a free hosting account to MVPs. I know Orcs has a great service so I was excited to give that a try, but I didn’t think their SQL storage would be enough for my blog. That is when I got the idea to give dasBlog a try. DasBlog stores all your data in xml files instead of using a SQL database. At first that sounds like a bad idea, but if it can support Hanselman’s blog, then surely my blog would have no problems at all. Plus it solves the SQL storage issue.

Now the harder question, how do you migrate all the content. At first I tried using the BlogML stuff to pull all my content out of Community Server, but I have a lot of content so I ended up getting lots of exceptions. I tried to hand code some solutions, but finally gave up. Then I got the idea to just take the simple route and write a custom program to read the data from my CS database and generate the XML files that dasBlog uses. So I used some Linq to SQL classes and wrote the XML using Linq to XML. It was fairly easy to do and it worked great.

The next step was to setup the redirects on the old site to point to the new site. I have all the articles redirecting and I think they all work (for the most part). I had to setup some custom redirects for some of the articles with non-standard characters in the titles, but other than that it was pretty easy. I also followed Scott’s post on canonicalize my URLs and using IIS7’s rewrite module. Orcs provides access to your IIS7’s manager remotely which works great.

I still need to migrate my articles, but I’ll get those done later today. Other than that it is a done deal. I’m very happy to be off the sqlxml.org domain which I still host at home and to be off of Community Server.

Lately, I wanted to thank Alexander Groß for the great theme which he created. I think this new blog is much easier to read and so far I’ve enjoyed the dasBlog software. I’ve even write a custom macro to put the RSS feeds on the category pages. I’m sure I’ll do some more customization down the road and post about as I go.

Hope you like the new blog!

Silverlight MVP

Posted in Silverlight at Friday, October 16, 2009 3:55 PM Pacific Daylight Time

On October 1st I was honored to receive the Microsoft Most Valuable Professional Award for Silverlight. I am very excited that I received this award and look forward to continuing my contributions to the Silverlight Community.

I wasn’t the only one to receive this honor as Tim Heuer blogged here:

As of today (01 OCT 2009) we welcome some new folks to the Silverlight group:

I’m very excited to be a part of the Silverlight MVPs group and look forward to working with them all.

Behaviors vs Subclassing in Silverlight

Posted in Silverlight at Wednesday, September 30, 2009 1:42 AM Pacific Daylight Time

As a Silverlight developer, when you want to add functionality to an existing control, you have two main options as I see it (if you want to get reuse from your code). You can either subclass the control or, as of Silverlight 3,  you can write a behavior for it. For example, one of the requests for the current Silverlight application that I’ve been working on was to have the TextBox select all the text when you tabbed to it or clicked in it. We can easily add this functionality using both of the above methods:

Here is how this could be done using subclassing:

public class SelectAllTextBox : TextBox 
{
    public SelectAllTextBox()
    {
        this.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
    }

    private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        this.SelectAll();
    }
}

And here is how you would write this as a behavior:

public class SelectAllBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.GotFocus += new RoutedEventHandler(AssociatedObject_GotFocus);
    }

    void AssociatedObject_GotFocus(object sender, RoutedEventArgs e)
    {
        ((TextBox)sender).SelectAll();
    }
}

The behavior has one more line of code and the added requirement of adding a reference to System.Windows.Interactivity.dll from the Blend 3 SDK. The bigger difference is how the code looks in our view when we add the control to it.

The subclassed control looks like (where ctrls is the controls namespace of our subclassed control):

<ctrls:SelectAllTextBox Text="{Binding MyText}" />

And the behavior looks like (where i is the System.Windows.Interactivity namespace and b is our behavior’s namespace):

<TextBox Text="{Binding MyText}">
    <i:Interaction.Behaviors>
        <b:SelectAllBehavior />
    </i:Interaction.Behaviors>
</TextBox>

Obviously the behavior is more verbose in this case than the subclassed approach.

Since both of these approaches work, which is the better approach? I think the subclassing is the easier approach, but I think the behavior would be the recommended approach. The reason is that I can build my SelectAll behavior today and then down the road build a different behavior and then selectively apply them to my TextBoxes as appropriate. However, if use the subclass approach I would automatically get the new behavior on all my controls which might not be what I wanted. It also means that if someone builds a better TextBox that I want to use that I would have to try to subclass that control, but with the behavior I could just apply it to the new control.

Update: A couple of quick updates. First, Alan Le pointed out that it depends on reuse. Obviously if you had to add the behavior to 20 TextBoxes it would take more time to use the behavior. However, Blend makes this a lot easier. Secondly, Brian mentioned in the comments that you could also use an attached property to do this so I thought I would quickly show what that might look like.

The code for the attached property would be:

public static class TextBoxProperties
{
    public static readonly DependencyProperty SelectAllProperty =
        DependencyProperty.RegisterAttached("SelectAll", typeof(bool), 
        typeof(TextBoxProperties), new PropertyMetadata(false, OnSelectAllChanged));

    public static void SetSelectAll(DependencyObject o, bool value)
    {
        o.SetValue(SelectAllProperty, value);
    }

    public static bool GetSelectAll(DependencyObject o)
    {
        return (bool)o.GetValue(SelectAllProperty);
    }

    private static void OnSelectAllChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue == true)
        {
            ((TextBox)d).GotFocus += new RoutedEventHandler(TextBoxProperties_GotFocus);
        }
    }

    private static void TextBoxProperties_GotFocus(object sender, RoutedEventArgs e)
    {
        ((TextBox)sender).SelectAll();
    }
}

And the Xaml would look like:

<TextBox Text="{Binding MyText}" ctrls:TextBoxProperties.SelectAll="true" />

I still think the Behavior is the best method to use since (at least in this case) we are just trying to add a behavior to the TextBox, not add significant functionality. The attached property also doesn’t feel right to me, but it does work just fine. Ultimately it comes down to preference and what method you like to use. :)

A “Default Command” for Silverlight

Posted in Avanade | Silverlight at Monday, September 28, 2009 7:23 AM Pacific Daylight Time

The current Silverlight application that I’m building has a Login view. One of the things that bugged me when I started using the application is that you would have to click the Login button after typing your password. I wanted to duplicate the default button behavior of HTML forms where when you hit the enter key it would trigger the default button on the form. I did some googling on the subject and came across this post by Patrick Cauldwell which is one way to solve the problem. However, in my case I had a username Textbox, a password Passwordbox, and a company Combobox and didn’t want to specify the button for each control.

So I create a simple solution of creating a content control that attaches to all the KeyUp events of all the child FrameworkElements in the content. To do this I used the FindChildren<T> extension method from the Avanade Silverlight Accelerator which is a toolkit we use internally at Avanade to speed up Silverlight development. The ContentControl exposes a DefaultCommand property which you then bind to the ICommand property on your ViewModel.

Below is a trimmed down example of the Login view. I’m using a variant of the RelayCommand/DelegateCommand as the LoginCommand here (see Laurent’s post on the RelayCommand for a good overview of Commands in Silverlight).

<ctrls:FormControl DefaultCommand="{Binding LoginCommand}">   
  <TextBox Text="{Binding Username, Mode=TwoWay}" />
  <PasswordBox Password="{Binding Password, Mode=TwoWay}" />
  <Button IsEnabled="{Binding LoginEnabled}" 
          cmds:ButtonClickCommand.Command="{Binding LoginCommand}" 
          Content="Login" />
</ctrls:FormControl>

There are many other things you could add to this but this is all the functionality that I needed and I decided to keep it simple. Download the class file (plus the extension method) below. Let me know if you find it useful!