Showing posts with label Client Architecture. Show all posts
Showing posts with label Client Architecture. Show all posts

Tuesday, June 9, 2009

.NET RIA Services is for RAD only!

A bit late to comment, but .NET RIA Services was announced at MIX09. I recently spent some minutes to see what the fuzz was all about.

.NET RIA Services is a framework proclaimed for Line of Business development which is supposed to make it easy to build N-tier application. The framework makes it easy to expose your domain logic on the server to the client, with validation, authorization, querying and so on. You do this by defining a DomainService like this (taken from the RIA Services Overview):

[EnableClientAccess()]
public class CityService : DomainService
{
  private CityData _cityData = new CityData();
  public IEnumerable<City> GetCities()
  {
      return _cityData.Cities;
  }
}
The EnableClientAccess attribute exposes proxies of your entities to the client by code generation. It also generates client access to your operations.

Sounds intriguing? Not really. I wouldn’t have an enterprise application rely so much on magic, but hey, it could maybe be done..

As you can see from the service, an entity called City is exposed to client:

public partial class City
{
  [Key]
  public string Name { get; set; }
  [Key]
  public string State { get; set; }
}

Why is the class partial you wonder..? As I said the framwork lets you validate your domain logic both on the server and client. To be able to do this you have to create a metadata class, also known as a buddy class:

[MetadataType(typeof(CityMetadata))]
public partial class City
{
  internal sealed class CityMetadata
  {
      [Required]
      public string Name;

      [Required]
      [StringLength(2, MinimumLength = 2)]
      public string State;
  }
}
Metadata classes provide a way to attach metadata to an entity without actually modifying the corresponding members on the entity itself. When you generate the client proxy you also get the validation attributes. Sounds intriguing? Not in my wildest dreams. To get validation you actually have to repeat every property of City. This is as DRY as it can possible get. Add the shared code functionality to the soup and you have yourself a maintainability nightmare. .NET RIA Services is for RAD only; prototypes and applications that never reach a satisfactory production quality. I would never ever use this in a production system.

Thursday, February 12, 2009

WPF and the Presentation Model Pattern

Over the last 6 months I've been working on a several projects where we have used Windows Presentation Foundation as our technology for creating GUI. When we started I began looking for presentation pattern that would best utilize the Data Binding capabilities in WPF and and at the same time could best interact with my domain model. In search for a suitable pattern I came across the Presentation Model by Martin Fowler. The Presenation Model, aka Application Model, aka Model-View-ViewModel pattern pulls the state and behavior of the view out into a model class that is part of the presentation layer. Since the presentation model holds the data that the view is going to render, there needs to be some kind of synchronization between the two. Based on the behaviour of the view, the presentation model changes it's state and automatically updates the view through Data Binding.

guiarch One can look at the view as a projection of the data in the Presentation Model. The Presentation Model has poperties for the information in the view and properties for state, typically disabling/enabling of buttons based on the current state of the view. The Presentation Model interacts with and updates the domain model through its properties. The following code illustates a typical presentation model for a project search view (in the context of my standard scrum application):

public class ProjectSearchPresentationModel : PresentationModel
{
private List<Project> mProjects = new List<Project>();
private DelegateCommand<string> mSearchCommand;

private DelegateCommand<Project> mSelectCommand;

public DelegateCommand<string> SearchCommand
{
 get
 {
     if (mSearchCommand == null)
         mSearchCommand = new DelegateCommand<string>(FindProjects);
     return mSearchCommand;
 }
}

public DelegateCommand<Project> SelectCommand
{
 get
 {
     if (mSelectCommand == null)
         mSelectCommand = new DelegateCommand<Project>(SelectProject);
     return mSelectCommand;
 }
}

public List<Project> Projects
{
 get { return mProjects; }
 set
 {
     mProjects = value;
     this.Notify(() => Projects);
     this.Notify(() => CanShowProjects);
 }
}

public bool CanShowProjects
{
 get { return Projects.Count() > 0; }
}

public void FindProjects(string searchText)
{
 var repository = IoC.Get<IProjectRepository>();
 Projects = repository.Query(project => project.Name == searchText);
}


public void SelectProject(Project project)
{
 ApplicationController.Instance.SelectProject(project);
}

public override void Refresh()
{
}
}
In the code behind of my view I instantiate a new ProjectSearchPresentationModel and set the DataContext of the view to my presentation model object:
public partial class ProjectSearchView : IView
{
private PresentationModel mPresentationModel;

public void Init()
{
 InitializeComponent();
 mPresentationModel = new ProjectSearchPresentationModel();
 DataContext = mPresentationModel;
}
}
The view now binds to the Projects property of the ProjectSearchPresentationModel and displays a list of Project objects based on the search criteria:
<StackPanel>
<Label Content="Enter customer name" />
<StackPanel Orientation="Horizontal">
 <TextBox Name="searchText" Width="100" />
 <Button Command="{Binding .SearchCommand}" CommandParameter="{Binding Text, ElementName=searchText}" Margin="5,0,0,0" Content="Search" />
</StackPanel>
</StackPanel>

<ListView Grid.Row="1" ItemsSource="{Binding .Projects}" Visibility="{Binding .CanShowProjects, Converter={StaticResource boolConverter}}">
<ListView.View>
 <GridView>
     <GridViewColumn Header="Action">
         <GridViewColumn.CellTemplate>
             <DataTemplate>
                 <Label>
                     <Hyperlink Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Views:IView}}, Path=DataContext.SelectCommand}" CommandParameter="{Binding .}">Select</Hyperlink>
                 </Label>
             </DataTemplate>
         </GridViewColumn.CellTemplate>
     </GridViewColumn>
     <GridViewColumn Header="Name">
         <GridViewColumn.CellTemplate>
             <DataTemplate>
                 <Label Content="{Binding .Name}" />
             </DataTemplate>
         </GridViewColumn.CellTemplate>
     </GridViewColumn>
 </GridView>
</ListView.View>
</ListView>
Note that I’m not using any event handlers in the code behind of the view. Instead I’m binding to Command properties defined in the ProjectSearchPresentationModel, which is hooked up to methods in the presentation model:
<Button Command="{Binding .SearchCommand}"
 CommandParameter="{Binding Text, ElementName=searchText}"
 Margin="5,0,0,0"
 Content="Search" />
public DelegateCommand<string> SearchCommand
{
get
{
 if (mSearchCommand == null)
     mSearchCommand = new DelegateCommand<string>(FindProjects);
 return mSearchCommand;
}
}

public void FindProjects(string searchText)
{
var repository = IoC.Get<IProjectRepository>();
Projects = repository.Query(project => project.Name == searchText);
}
The generic DelegateCommand is a class that implements the ICommand interface and is similar to the DelegateCommand found in the Prism framework. With commands I can keep the code behind of the view almost free from code. In my opinion the Presentation Model pattern is extremely powerful in combination with WPF. I find it both effective and easy to work with and lets me seperate the view from the domain model in an elegant way, which in turn makes it easy to test the view. This is how I do it. Stay tuned for more!