# Wednesday, 25 November 2009

I’m trying to get a handle on WF 4 (which is awesome, BTW) and currently working on persistence.  We have a need to encrypt the workflow instance data, and it took me quite some time to figure out how that might best be done.  The biggest drawback to working with WF 4 right now is that the documentation is pretty lame.  There are very few samples, and beta 2 hasn’t been around long enough to generate the “this is how you solve that problem” blog posts we’ve all come to depend upon.  I looked at PersistenceParticipant, but couldn’t see a good way to make that do what I wanted, then a bunch more time trying to figure out what was going on in the SqlWorkflowInstanceStore, etc. 

I think I’ve got a workable solution, although I’ve yet to actually try it out.  Turns out that the SqlWorkflowInstanceStore keeps all that good data in varbinary(MAX) columns, and only messes with them via a set of stored procs that get created when you create the instance store schema.  It should be an easy thing to modify said stored procs to use native SQL 2005/2008 column level encryption, without having to change the schema at all. 

I’ll let you know if it works…

Wednesday, 25 November 2009 13:30:39 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

This one stumped me for a bit today, so I wanted to get it out there for the search engines to find... I created a new WCF Service Library project in VS 2010, taking all the defaults and targeting .NET 4.0. I needed to add a [WebGet] attribute so that I could make REST calls to the service. To do that, you need a reference to System.ServiceModel.Web.dll. It didn't show up on the list of .NET references in the Add Reference... dialog. OK, weird. So then I tracked down the file manually and added it. It got added to the list of references, but showed up with the yellow-triangle "I don't know how to find this reference" icon. Huh.

The problem turned out to be that for some reason, the project got created with a target framework of .NET 4.0 Client Profile, which doesn't include that assembly. Once I switched to the full .NET 4.0 target, it works just fine. The Client Profile seems like a strange choice for a WCF Service Library.

Wednesday, 25 November 2009 13:23:57 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, 09 November 2009

So I’m trying to figure out how to use WF 4 as a controller for a Prism app, and already I’m running into some interesting behavior.  First off, in anything but a very simple solution, custom activities don’t show up in the toolbox like they should.  That’s not a huge deal, but annoying.

Of greater interest (concern?) is the fact that if I put my workflow XAML file in the main WPF app solution, everything builds and runs just fine, except the workflow does absolutely nothing.  It just finished successfully, having run none of it’s activities.  If I take exactly the same XAML file and put it in another assembly, then run it from the WPF app, it works just like it should.  I’m guessing this is a byproduct of the new unified XAML engine, but I haven’t had time (or inclination really) to delve.  Mostly it just means I have to have at least one superfluous assembly, which for now isn’t too high a price to pay. 

The day I installed beta 2, I managed to crash the workflow designer about 10 times, but it seems to have settled down now.  Overall, I really appreciate the new model for WF, which seems much more composable and easy to use. 

Monday, 09 November 2009 09:09:28 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 06 November 2009

I realize this is a bit late, but as of just about 4 weeks ago I’m now the Architect at Eid Passport.  I’m really looking forward to building some cool stuff, with a team that’s had quite a bit of experience in this space. 

In short, Eid Passport makes perimeter security systems for secure facilities, and manages access to those facilities by vendors.  For example, say you are the Coke delivery guy at a military base.  It’s a hassle to get through the gate every time you deliver, since they have to make sure it’s OK for you to be on the base.  Now the Coke guy has the option of going to our kiosk at the base and signing up for an access card that will allow him to spend much less time getting in and out.  We do some background checks, employment verification (does he still really work for Coke, etc.) and then issue a credential that he can use to get through the gate.  Now Coke delivery guy can make N more deliveries in a day because he’s not spending time at the gate.  This is a new domain for me, so there’s a lot to learn, but it’s pretty exciting stuff.  All the way from a handheld scanner that reads all kinds of cards to back end access control and data processing servers. 

If any of that sounds interesting to you, we’re looking for some additional developers.  There are instructions on the website (see above) for how to submit your resume if you are interested.

Friday, 06 November 2009 09:32:28 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, 17 June 2009

We’ve added some new classes to the SoftSource training calendar, including a one-day Blend 2 class, and SQL 2008 for Developers.  Other offerings coming up are “Agile in a Day”, WPF, WCF, ASP.NET 3.5, LINQ, Silverlight, and of course, C#.  Discounts available for multiple students from the same organization, and custom on-site training also.

Wednesday, 17 June 2009 10:19:27 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 11 June 2009

A month or so ago I posted on a solution for simulating “default button” semantics in a Silverlight app, meaning that if you are entering text in a text box and you hit the enter key, the “default button” for the “page” should be pressed.  Very natural for form entry, etc. 

An issue came up (discovered by John Papa) with the solution in a Prism app, because my solution depends on being able to find the “default” button in the visual tree using the FindName method.  That means that you have to be high enough up the visual tree to find the button, since it only works “down” the tree.  In a Prism app, it’s not necessarily clear where “high enough” might be.  Plus, because the solution requires unique names, and Prism modules may have nothing to do with one another, they may have duplicate names, etc.

Here’s a revision to the solution that doesn’t require unique names, and doesn’t require any static references that might interfere with proper garbage collection…

First, a new object called DefaultButtonHub that keeps track of the relationship between text boxes and buttons.  It also exposes an Attached Property that takes a DefaultButtonHub reference so we can hook up text boxes and buttons to the “hub” in XAML.

public class DefaultButtonHub
{
   ButtonAutomationPeer peer = null;

   private void Attach(DependencyObject source)
   {
       if (source is Button)
       {
           peer = new ButtonAutomationPeer(source as Button);
       }
       else if (source is TextBox)
       {
           TextBox tb = source as TextBox;
           tb.KeyUp += OnKeyUp;
       }
       else if (source is PasswordBox)
       {
           PasswordBox pb = source as PasswordBox;
           pb.KeyUp += OnKeyUp;
       }
   }

   private void OnKeyUp(object sender, KeyEventArgs arg)
   {
       if(arg.Key == Key.Enter)
           if (peer != null)
               ((IInvokeProvider)peer).Invoke();
   }

   public static DefaultButtonHub GetDefaultHub(DependencyObject obj)
   {
       return (DefaultButtonHub)obj.GetValue(DefaultHubProperty);
   }

   public static void SetDefaultHub(DependencyObject obj, DefaultButtonHub value)
   {
       obj.SetValue(DefaultHubProperty, value);
   }

   // Using a DependencyProperty as the backing store for DefaultHub.  This enables animation, styling, binding, etc...
   public static readonly DependencyProperty DefaultHubProperty =
       DependencyProperty.RegisterAttached("DefaultHub", typeof(DefaultButtonHub), typeof(DefaultButtonHub), new PropertyMetadata(OnHubAttach));

   private static void OnHubAttach(DependencyObject source, DependencyPropertyChangedEventArgs prop)
   {
       DefaultButtonHub hub = prop.NewValue as DefaultButtonHub;
       hub.Attach(source);
   }

}

Basically we’re expecting that both the text boxes and the button will register themselves with the “hub”.  If it’s a button that’s being registered, we wrap it in a ButtonAutomationPeer so we can “press” it later.  If it’s a text box, we hook up a KeyUp handler that will “press” the button if it’s there.  The requirement in the XAML is only marginally heavier than in my previous solution…we have to add a resource of type DefaultButtonHub, and point the button and text boxes at it using the {StaticResource} markup extension.

<UserControl x:Class="DefaultButton.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:my="clr-namespace:DefaultButton"
    Width="400" Height="300">
    <UserControl.Resources>
        <my:DefaultButtonHub x:Key="defaultHub"/>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="theText" Grid.Row="0"
                 my:DefaultButtonHub.DefaultHub="{StaticResource defaultHub}"/>
        <Button x:Name="theButton" Grid.Row="1" Content="Default"
                Click="theButton_Click" my:DefaultButtonHub.DefaultHub="{StaticResource defaultHub}"/>
    </Grid>
</UserControl>

Note that the new DefaultHub attached property is applied to both the text box and the button, each pointing the the single resource.  This way everything gets wired up property, there isn’t any problem with name resolution (aside from the usual resource name scoping) and everything will get cleaned up if the form needs to be GC’d.

Thursday, 11 June 2009 12:03:22 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 05 June 2009

Last time, I talked about how to build a Domain Service from scratch using whatever POCO you have lying around.  Now it’s time to talk about how that works on the client side…

One of the coolest things about RIA Services is that you don’t even have to “Add Service Reference…” to get a reference to the Domain Service.  If your Silverlight project is linked to the ASP.NET project correctly (see the RIA Services doc for how this works) the build steps will take care of generating the right code in your Silverlight project, and away you go.  There are several ways of accessing the service client-side, from dead-easy to a bit more involved.  We’ll start with dead easy. 

The very easiest way to get things hooked up is to use the DomainDataSource control.  It wraps your DomainDataContext (the client-side generated bit) with a data source you can bind directly against in XAML.

<ria:DomainDataSource x:Name="PeopleDataSource" LoadMethodName="LoadPersons" AutoLoad="True">
  <ria:DomainDataSource.DomainContext>
      <services:PeopleDomainContext/>
  </ria:DomainDataSource.DomainContext>
</ria:DomainDataSource>
<dataControls:DataForm x:Name="dfPeople" CanUserAddItems="True" CanUserDeleteItems="true"
                     ItemsSource="{Binding ElementName=PeopleDataSource, Path=Data}" 
                     ItemEditEnded="dfPeople_ItemEditEnded">
</dataControls:DataForm>

The LoadMethodName attribute on the DomainDataSource tells it what method on the DomainContext to call in order to correctly populate the data context.  You can also pass parameters defined in XAML to the Load method if you only need to load a subset.  The DataForm control is bound to the Data property of the DomainDataSource, and away you go.  You get this

image

Because the Insert/Update/Delete methods are implemented on the server-side DomainService, the DataForm automagically enables the edit, add and delete buttons at the top.  If I edit or add a record, the save button shows up…

image

Pressing either the Save or Cancel button fires the ItemEditEnded event, which we can grab to submit the changes back to the server

private void dfPeople_ItemEditEnded(object sender, DataFormItemEditEndedEventArgs e)
{
  if (e.EditAction == DataFormEditAction.Commit)
      PeopleDataSource.SubmitChanges();
}

this is the very simplest case.  Calling SubmitChanges() here will send the edits/inserts up to the server right away.  For the sake of bandwidth, etc. I might want to implement my own “Save” button that batches up a whole set of change to the server rather than committing each edit individually.  You would still call PeopleDataSource.SubmitChanges, but not in response to the DataForm’s events. 

One of the great things about the way this works on the client side is that way the data validation attributes we set on the server-side POCO objects get propagated to the client.  For example, the server side LastName property looks like this (at least in the metadata class…)

[Required]
[RegularExpression("[a-zA-z]*")]
public string LastName;

The property that gets generated on the client side is

[DataMember()]
[RegularExpression("[a-zA-z]*")]
[Required()]
public string LastName
{
  get
  {
      return this._lastName;
  }
  set
  {
      if ((this._lastName != value))
      {
          this.ValidateProperty("LastName", value);
          this.RaiseDataMemberChanging("LastName");
          this._lastName = value;
          this.RaiseDataMemberChanged("LastName");
      }
  }
}

It maintains the [Required] and [RegularExpression] attributes.  Plus, in the property setter, it calls ValidateProperty, which uses reflection to examine those attributes and throw validation exceptions if necessary.  By default, then, I get UI on the Silverlight client for validation.

image

The DataForm provides the UI around both the field in question and the summary at the bottom.  In this case, I probably don’t want to tell the user what RegEx I’m validating against, so I need to add the ErrorMessage property to the validation attribute

[Required]
[RegularExpression("[a-zA-z]*", ErrorMessage="Alpha characters only please!")]
public string LastName;

image

When that error is corrected and I press the Save button, the Custom Validation routine is applied (see last post for details)

image 

When all the errors are corrected, and the save happens (and gets committed back to the server) the DataForm is updated to show the correct ID value (from the server) as well as the calculated Age property.

image

For next to no work, I get a pretty good user experience for browsing, editing, inserting and deleting records.  If I wanted a bit more control, I could load the data into the DataContext myself, and then setup the databinding, rather than using the DomainDataSource in XAML

private PeopleDomainContext _context = new PeopleDomainContext();

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  if (_context.Persons.Count == 0)
  {
      _context.Loaded += (s, arg) => loadPeople();
      _context.LoadPersons();
  }
  else
      loadPeople();
}

private void loadPeople()
{
  dfPeople.ItemsSource = _context.Persons;
}

This would give me an opportunity to only load some people based on parameters, or whatever else I wanted to do to affect the loading of data before the data binding happens. 

Next time… more cool things you can do with the DomainDataContext

Friday, 05 June 2009 14:47:59 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, 02 June 2009

Most of the demos/samples I’ve looked at so far for RIA Services have started with a LINQ to SQL or ADO.NET Entity model and generated Domain Service classes from those.  I decided to start from something super simple (a POCO, if you will) and work up from there.  I started with a canonical  “Person” class

public partial class Person : INotifyPropertyChanged
{
   #region INotifyPropertyChanged Members

   public event PropertyChangedEventHandler PropertyChanged;

   #endregion

   protected virtual void Changed(string propertyName)
   {
       PropertyChangedEventHandler handler = PropertyChanged;
       if (handler != null)
       {
           handler(this, new PropertyChangedEventArgs(propertyName));
       }
   }

   private int _personId;
   public int PersonId
   {
       get
       {
           return _personId;
       }
       set
       {
           if (_personId != value)
           {
               _personId = value;
               Changed("PersonId");
           }
       }
   }

   private string _firstName;
   public string FirstName
   {
...
   }
   private string _lastName;
   public string LastName
   {
...
   }
   private System.DateTime _birthDate;
   public System.DateTime BirthDate
   {
...
   }
}

Nothing to see here.  It’s just a simple POCO that supports INotifyPropertyChanged for databinding.  Note that it’s a partial class…  The simplest path would be to add RIA Services attributes directly to these properties for things like data validation, but I wanted to try out all the features, so I split out the metadata into another file

[MetadataTypeAttribute(typeof(RiaServices.Web.Person.PersonMetadata))]
public partial class Person
{

   internal sealed class PersonMetadata
   {
       [Key]
       [Required]
       public int PersonId;

       [Required]
       [RegularExpression("[a-zA-z]*")]
       public string FirstName;

       [Required]
       [RegularExpression("[a-zA-z]*")]
       public string LastName;

       [Required]
       public DateTime BirthDate;
   }
}

This is kind of an interesting trick, and allows me to separate out all the RIA specific metadata from the original class definition.  This makes total sense when you look at the way they handle LINQ to SQL, for example.  In that case you already have Entity classes defined by the LINQ to SQL wizard, so this extra metadata class allows you to associate the right attributes without touching the (generated) LINQ to SQL classes.  Clever.  Notice that the metadata class uses fields, not properties, and just matches the names for the sake of simplicity.

In this case, the additional metadata defines data validation rules that get enforced both server and client side.  There are other attributes to enforcing string length and ranges. 

This all works because RIA Services generates “proxy” entity classes on the client side that are Silverlight compilable and also DataContracts (for serializing, which is cool…).  However, what happens if I have a calculated property that’s not just storage?  There’s a solution for that too, and it involves another piece of the partial class

public partial class Person
{
   [Shared]
   public int Age
   {
       get
       {
           this.Changed("Age");
           return Convert.ToInt32(Math.Floor((DateTime.Now - _birthDate).Days / 365.25));
       }
   }

}

This bit goes in a file called Person.shared.cs, and it will be copied to the client project and compiled there as well as on the server.  The [Shared] attribute marks the bits that need to be thus propagated.  Again, clever.  Of course, any such shared code has to compile in Silverlight.

The other piece of code I want to share (using the same method) is a custom validator.  In addition to the [Required] or [RegularExpression] attributes used above, you can register a custom validation routine that can examine the state of the entity as a whole.  The validation routine looks like this

[Shared]
public class PersonValidator
{
   public static bool IsPersonValid(Person p, ValidationContext context, out ValidationResult result)
   {
       bool valid = true;

       result = null;

       if (p.Age > 130)
           valid = false;

       if (!valid)
       {
           result = new ValidationResult("Birthdate is invalid, people can't be that old", new []{"BirthDate"});
       }

       return valid;

   }
}

That’s in a file called PersonValidator.shared.cs, so that it will be available client and server-side.  It’s associated with the Person entity with an additional attribute

[CustomValidation(typeof(PersonValidator), "IsPersonValid")]
[MetadataTypeAttribute(typeof(RiaServices.Web.Person.PersonMetadata))]
public partial class Person
...

With the Person entity all ready, I can expose it to the client by creating a new DomainService class with methods for Get, Insert, Update, Delete, etc.

[EnableClientAccess()]
public class PeopleDomainService : DomainService
{
   public IQueryable<Person> GetPersons()
   {

       return PeopleData.Persons.AsQueryable<Person>();
   }

   public IQueryable<Person> GetPerson(int personId)
   {
       return (from p in PeopleData.Persons
               where p.PersonId == personId
               select p).AsQueryable<Person>();
   }

   public void UpdatePerson(Person person)
   {
       Person oldP = (from p in PeopleData.Persons
                      where p.PersonId == person.PersonId
                      select p).FirstOrDefault();

       if (oldP != null)
       {
           PeopleData.Persons.Remove(oldP);
           PeopleData.Persons.Add(person);
       }
   }

   public void InsertPerson(Person person)
   {
       if (person.PersonId == 0)
       {
           int max = PeopleData.Persons.Max(p => p.PersonId);
           person.PersonId = max + 1;
       }

       PeopleData.Persons.Add(person);
   }

   public void DeletePerson(Person person)
   {
       Person oldP = (from p in PeopleData.Persons
                      where p.PersonId == person.PersonId
                      select p).FirstOrDefault();

       if (oldP != null)
       {
           PeopleData.Persons.Remove(oldP);
       }
   }
}

PeopleData.Persons in this case is a List<Person> that’s populated with some sample data.  The [EnableClientAccess] attribute causes the build-time bits to generate a client side proxy for calling the service without the client project needing a service reference.  It really makes the Silverlight and the Web projects feel like parts of the same app rather than disconnected pieces. 

The corresponding class that is generated on the client side is a DomainDataContext, which feels much like a LINQ to SQL DataContext only it’s lazy-loaded like the Astoria ones.  The GetPersons method on the server results in LoadPersons on the client, etc.  If I hadn’t implemented the Insert/Update/Delete methods on the server side, the DomainDataContext would simple behave like a read only data source.  This model works really well with the DataForm class.  If I set the ItemsSource of the DataForm to the Persons “table” in the client side data context, it will properly enable/disable the add/delete buttons depending on the capabilities of the data context.  Neat. 

Coming in future posts… hooking up the PersonDataContext to the Silverlight 3 UI, and in ASP.NET

Tuesday, 02 June 2009 15:53:18 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 28 May 2009

Shaun and I will be doing a one-day training, “Practical Silverlight 3”, in lovely San Francisco, CA on July 8th.  It’s a full day of Silverlighty goodness, starting with the basics and movin’ on up.  We like to think of it as a 300 level technical introduction to the subject, so you will come away with a better understanding of the fundamentals, and where to look next.

Topics include

  • An introduction to Silverlight 3
  • All about controls (styling, templating, building your own)
  • Integrating with the browser
  • Communicating with the server via WCF, REST/POX, Sockets, you name it

If you are or will be in NorCal, come check it out.  It’s a good introduction for a very reasonable price.

Thursday, 28 May 2009 16:38:16 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, 26 May 2009

SoftSource developer Prashant Sinha is going to be presenting on “Production Debugging for Silverlight and ASP.NET” at Code Camp.  Prashant is a debugging wiz, and teaches our two-day .NET debugging course, so this should be a very useful session. 

Tuesday, 26 May 2009 13:51:11 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |