Sunday, October 11, 2009

Australia Tour

I’m spending the next two weeks in Australia to teach some classes and speak at some user groups. This week, 12-16 Oct, I am teaching our Architect Master Class through our training partner Readify in Melbourne. Next week I’ll be teaching our WCF Master Class in Sydney 19-23 Oct, also through Readify.

The timing worked out perfectly that I also get to be the guest speaker at a user group in each city as well. On 13 October, I’ll be presenting a talk on Prism at the Victoria .NET User Group. On Wed 21 October, I’ll be giving two sessions at the Sydney .NET User’s Group on Prism and WF 4.

It’s always fun to give talks to user groups, but it is extra special fun to get to give user group talks in other countries. Really looking forward to both, as well as the classes. And spending two weeks in Australia doesn’t suck one bit either. :)





Sunday, October 11, 2009 5:02:10 AM (GMT Standard Time, UTC+00:00)
Comments [2]  | 


  Monday, October 05, 2009

Avoiding Memory Leaks with CompositeCommands

I had some good follow on discussions from my recent post on Graceful Shutdown with Ward Bell and Jeremy Miller about how “graceful” my shutdown example really was. They argued a point that I agreed was a big weakness with the approach: sending information back to the shell about whether to shutdown through a command parameter is not a very clean path of communication. Also, my arguments about using a command vs a pub-sub event were difficult to defend. Either one would work fine, but both suffer this same problem of obscure communication paths.

Jeremy also pointed out that the use of Prism CompositeCommands is always a little dirty and hazardous for two reasons. First, they are typically used as globals – a static singleton instance of the CompositeCommand that any control can source and any other part of the app can hook up to through the CompositeCommand.RegisterCommand method. And we all know that globals are evil.

The other problem with CompositeCommands is that it is too easy to have some chunk of code register a child command with the RegisterCommand method and then forget that now the CompositeCommand holds a reference chain back to the child command, the object on which the child command is a member, and the object on which the child command handler method exists.

In my simple example, there was the smell of a potential memory leak – an app that lets you open multiple documents, each document gets its own view and view model, and the view models are the command handlers for composite commands. Since those views are being dynamically created (in this case in response to another composite command for “New”), the registration is being done on the fly as their view models are initialized. So this begs the question of when do they get unregistered so that you don’t leak memory (in the form of residual command references into view models that are no longer being used). Prism commands do not currently use weak references like the Prism events do, although you could modify them to do so without too much difficulty.

You can get the updated code for this post here.

With the original sample code from my last post, it turned out this was not really a problem because the sample provided no way to close a view once opened. But it was just a sample focusing on the communication path for the Closing event after all. But say it was a real app and you were going to allow the user to close a document. I’ve modified the sample to allow closing a document through an X button on the tabs that the documents get opened in.

10-5-2009 8-40-21 AM

I didn’t take the time to beautifully style it, so forgive me my artistic ineptitude. But now that there is a mechanism to close the views, presumably the references to the views and view models are released when their document is closed, but if we don’t make sure we call UnregisterCommand in that process, we will have an effective memory leak – the CompositeCommands for Shutdown and Save will be holding references to the view models keeping them from being garbage collected. Each new document we open gets a new view and ViewModel instance, registers it, and over time we would see the memory of this app grow and grow.

So the direct solution is to ensure through whatever means practical to call UnregisterCommand before all refs to the ViewModel go away. Lets take a quick look at the code for this sample to get that done.

I added a data template to the shell where the TabControl is defined to add the X buttons into the tab headers:

<DataTemplate x:Key="ButtonTabItem">
    <DockPanel>
        <Button DockPanel.Dock="Right" 
          Command="{Binding Path=Content.DataContext.CloseCommand, 
          RelativeSource={RelativeSource AncestorType=TabItem}}">X
        </Button>
        <TextBlock Text="{Binding Path=Content.DataContext.DocumentTitle,
           RelativeSource={RelativeSource AncestorType=TabItem}}" VerticalAlignment="Center"/>
    </DockPanel>
</DataTemplate>

 

You can see the binding code is expecting a CloseCommand to be exposed from the ViewModel which is the DataContext of the view, and the view is the Content of the TabItem. The DocumentEditorView did not have to be modified at all, but the CloseCommand was added to the ViewModel as a DelegateCommand, as well as a Closed event to notify the controller:

public DocumentEditorViewModel()
{
    SaveCommand = new DelegateCommand<object>(OnSave, OnCanSave);
    SaveCommand.IsActive = true;
    Commands.SaveCommand.RegisterCommand(SaveCommand);

    ShutdownCommand = new DelegateCommand<CancelEventArgs>(OnShutdown);
    Commands.ShutdownCommand.RegisterCommand(ShutdownCommand);

     ...
    CloseCommand = new DelegateCommand<object>(OnClose);
 }

public DelegateCommand<object> CloseCommand { get; set; }
public event Action<DocumentEditorViewModel> Closed = delegate { };

private void OnClose(object obj)
{
    // Prompt to save, save document, etc.
    Commands.ShutdownCommand.UnregisterCommand(ShutdownCommand);
    Commands.ShutdownCommand.UnregisterCommand(SaveCommand);
    Closed(this); // Notify controller through an event, could also use a Prism event if others might care...
}

 

In this case, since the command handling for closing can be collocated with the code that did the registration, it is easy to make sure that we UnregisterCommand as part of the closing process. The controller is the one that takes care of presenting the views in this case, so the event is fired so the controller can choose to do what is appropriate, which in this case is to just remove the view from the region. That takes a bit of convoluted code to locate the view that corresponds to the ViewModel since the two are loosely coupled.

private void OnViewClosed(DocumentEditorViewModel vm)
{
    vm.Closed -= OnViewClosed;
    IRegion region = m_RegionManager.Regions[Constants.DOCUMENTREGION];
    DocumentEditorView viewToRemove = null;
    foreach (var view in region.Views)
    {
        DocumentEditorView docView = view as DocumentEditorView;
        if (docView == null) continue;
        if (docView.DataContext == vm)
        {
            viewToRemove = docView;
            break;
        }
    }
    if (viewToRemove != null)
        region.Remove(viewToRemove);
}

 

So for this simple example, it was not too terribly hard to make sure a memory leak did not happen with the use of the CompositeCommand once I added the functionality to close a view. However, what you can see emerging here is that the complexity is growing disproportionate to the work that this little sample is really doing. With a large app with many views/ViewModels, lots of commands and cross module communications, etc. this could get out of control pretty quick, and it would be easy to miss a place where you are not unregistering correctly.

The net result of all this is that the use of CompositeCommand works, but is not completely satisfying here, and especially not in a large complex  app. Modifying CompositeCommand to use weak references would be one choice, or switching to Prism events for the communications would be another choice.

Coupled with this challenge of potential memory leaks is the scenario of the previous post – graceful shutdown communications – is a another responsibility relative to view management that really cries out for some centralized management. Then you have the view activation/deactivation that I will talk about in my next post that also requires some common handling, and it turns out that what you really need is a pattern/abstraction that Prism does not yet really provide – you need a screen conductor / director of some sort that keeps track of what views are being presented, when they are activated/deactivated, whether they can close, etc.

Jeremy is working on a chapter for his upcoming book  that will cover an approach to this problem. I and others are trying to wrap our heads around the best way to tackle this problem. Ward Bell has suggested a “Close Service” that is responsible for coordinating the shutdown and he spiked an implementation of this that definitely felt cleaner than doing the back-channel communications through command or event arguments. I’ll be sure to blog more about this as my thoughts gel on it and if I can get a decent implementation put together, or will link to whoever beats me to it publicly first.

But before I get there, I do want to explain the IActiveAware mechanism of Prism, since it was important in getting the application to work correctly as well and is severely under-documented in the Prism docs. So that will be my next post, stay tuned…

You can get the updated code for this post here.





Monday, October 05, 2009 1:22:17 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Wednesday, September 30, 2009

Deep Fried Bytes – Workflow Part 2 is up

Part 2 of my interview on workflow foundation, past, present, future, and focus on workflow services is up and available for your listening pleasure (or torture as the case may be).

dfb





Wednesday, September 30, 2009 1:00:43 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Monday, September 21, 2009

Deep Fried Bytes episode Part 1 live

A couple months ago I recorded an interview on the state of affairs of Windows Workflow Foundation, with the focus on Workflow Services, on Deep Fried Bytes. The recording has been broken into two parts because we talked for quite a while and part one has gone live. You can check it out here:

dfb





Monday, September 21, 2009 9:34:22 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Saturday, September 05, 2009

Supporting Graceful Shutdown and Saving on Close From a WPF Prism App

When you start building applications the Prism way, your UI logic can be spread out across any number of loosely-coupled, independent modules and their supporting code. This is a good thing in terms of breaking up the functionality of your application into reusable components and being able to distribute the work across multiple developers or teams. However, the decentralizing of the UI logic can lead you to scratch your head frequently when you need to implement some piece of functionality that sort of naturally feels like the main window has to handle it all.

A common requirement that is one of these common head scratchers is what to do when you want to prevent the application from shutting down until all work in progress (unsaved documents, pending downloads, etc.) is complete. This came up (again) with a customer the other day, so I figured it would make a good post (thanks for the idea John :) ).

In a Prism app, the code that performs those actions and manages the state associated with them should be implemented within the modules that are loading into the application, and that code probably belongs in a ViewModel or Controller that is supporting the associated views.

So when the user clicks on the red X to close the application, or invokes some other command from the menu or toolbar that indicates it is time to close the application, you need a clean communication path from the shell down to all chunks of code that may need to vote on whether the application should be allowed to shut down right now.

Picking a Communication Option

Prism offers two loosely-coupled communication mechanisms: Prism events and commands. One approach that might occur to you is to use Prism events and have the shell publish a shutdown event, and have the module code subscribe and handle it. This could work, but part of the pattern of pub-sub events is that the publisher should not know or care if there are any subscribers out there, nor should it care what the subscribers do if they are there.

So if you just wanted to notify the module code that shutdown is happening, you could use a Prism event, but the problem is that you probably need to block the shutdown until they have all done their clean up, and you often need to be able to cancel shutdown if there is unsaved state or incomplete tasks.

One of the key differentiators between events and commands in my mind is that commands represent an action taking place for which there is an expectation that there will be some handling code out there. So for a shutdown communication to the modules, a command is a better way to go. And the way Prism CompositeCommands work, all of the contained command handlers will be invoked before the execution of the command is complete.

In general, a command invoker is not expecting any results back from the handlers. However, to support the cancellation of shutdown, we would need to effectively pass arguments back to the invoker to let it know whether to complete the shutdown. To do this, we can just piggy back on a well-established pattern in WPF and Windows Forms – pass a CancelEventArgs argument as the command parameter, and allow the handlers set the Cancel property of that parameter to true if they don’t want shutdown to happen.

Putting it Together

To demonstrate one way to put this together, I’ve put together a simple Prism application that is like a simple Wordpad of sorts. You can fire it up, open multiple documents in tabs, edit them, and save them independently. You can see the app running below. A few minor bells and whistles include setting the tab header to the document title, and showing “dirty” documents by making their tab header bold/italic. The New command in the toolbar is always enabled, but the Save command is only enabled if the currently active document is dirty. I’ll do a follow on post about this aspect, which uses the  IActiveAware facility of Prism.

DocEditorApp

The logic code for supporting an individual instance of an editor views is fully implemented in the ViewModel class for the view, DocumentEditorViewModel.

There is also a controller class that takes care of creating the instances of the view when the New command is invoked.

I’m not going to drill into all aspects of the application architecture, but you can take a look at it as a fairly well organized example of a Prism app if you download the sample code. The basic project structure is shown below. I have a ShellApp that is the WPF application project. It contains a bootstrapper like most Prism apps that gets things going by presenting the shell. The MainWindow class is the shell window, and has two regions in it: a MainToolbarRegion and a DocumentRegion. The toolbar is (not surprisingly) a Toolbar, and the document region is just a TabControl. There is also a StatusBar at the bottom to show an indication of why close is not happening if one of the documents needs to be saved.

ProjectStructure

The SomeApp.Common is just a class library that contains the shared types between the shell and the modules – specifically some constants and the commands in this case.

The SomeDocumentModuleLib is the only module in this example, and contains the SomeDocumentModule, the DocumentController, the DocumentEditorViewModel, and its supporting DocumentEditorView. The view class (DocumentEditorView) is very simple, just a TextBox and the IActiveAware implementation I’ll talk about in a subsequent post.

The controller is called by the module’s Initialize method to get things going, and it populates the toolbar with the New and Save command buttons using Prism regions, and also has the handling code for New, which simply creates a new instance of a view and a viewmodel and marries them (sets the view’s DataContext = viewmodel).

The ViewModel is where the action is at for both the Save command and the Shutdown command that I am really trying to focus on here.

Notifying ViewModels of Shutdown

To get the word out to the ViewModel instances for open documents when someone goes to close the application, you have to first start with the WPF Window.Closing event that is fired. That event passes a CancelEventArgs allowing you to prevent the closing of the Window. But first off we don’t want to do logic handling in a view (the Shell), and second, the Shell is supposed to be fairly stupid about what the app components want to do about the event anyway. So we need a clean way to dispatch the event out as a command and get results back to decide whether to let the close happen or not.

The way I chose to approach it is to use a Prism CompositeCommand as the form of communication. Each ViewModel (or other interested background code) can provide a command implementation for that command, and in that implementation they can decide and modify the argument that is passed to indicate whether they are OK with the shutdown or not.

So starting at the source, we first have to handle the Closing event at the Window level:

<Window x:Class="ShellApp.MainWindow"
    ... 
    Closing="OnWindowClosing"
     >

To dispatch the command to others, we need a command definition.

public static class Commands
{
    ...
    public static readonly CompositeCommand ShutdownCommand = new CompositeCommand();
}

The ShutdownCommand is the one we are focusing on here.

The code behind handler for the Closing event basically needs to execute the Shutdown event and pass along the CancelEventArgs as a command parameter, allowing the handlers of the command to potentially set Cancel to true:

private void OnWindowClosing(object sender, CancelEventArgs e)
{
    if (Commands.ShutdownCommand.CanExecute(e))
        Commands.ShutdownCommand.Execute(e);
    if (e.Cancel)
        m_StatusText.Text = "One or more documents need saving before you can shutdown";
}

 

The way the CompositeCommand works in Prism, it will go out to all command handlers that register with the command and invoke their handling code.

The DocumentEditorViewModel provides the implementation of that command, one for each instance of an open document:

public DocumentEditorViewModel()
{
    ...
    ShutdownCommand = new DelegateCommand<CancelEventArgs>(OnShutdown);
    Commands.ShutdownCommand.RegisterCommand(ShutdownCommand);
}

public DelegateCommand<CancelEventArgs> ShutdownCommand { get; set; }

private void OnShutdown(CancelEventArgs args)
{
    if (IsDirty)
    {
        args.Cancel = true;
    }
}

The view model also maintains the dirty state of the document and uses it to drive both the enablement of the Save command, as well as to decide whether to allow shutdown. If the document is dirty, it simply sets the CancelEventArgs.Cancel property to false. Since the same argument is passed by reference to all the handlers of the command, if any one sets it to true, Closing will not happen.

That’s all there is to it. Piece of cake, right? Clean, simple, loosely coupled communications that achieves the end goal. Shell doesn’t have to have any knowledge of what it takes to allow the app to shut down, and the individual chunks of code that care don’t have to know about each other.

Any questions or comments, please post a comment and I’ll get back to you.

You can download the full sample app code here.





Saturday, September 05, 2009 4:35:02 PM (GMT Standard Time, UTC+00:00)
Comments [2]  | 


  Sunday, August 16, 2009

INETA UG Talks This Week

I gave two talks in SoCal this week, one at the San Diego .NET User Group Connected Systems SIG in San Diego and one at the South Bay .NET User Group in Torrance.

The San Diego talk was titled Exercise WCF Best Practices and was a collection of practices with context and explanation on employing features and capabilities in the WCF stack in the best way. I talked about server side considerations including interface and layer separation, instancing model, exception handling, security model, and hosting, as well as client side considerations such as proxy creation, caching of proxies, and exception handling on the client side.

The slides and demos for this talk can be downloaded here:   Slides    Demos

The Torrance talk was A First Look at WF 4, which covered all the new features coming in WF 4. I covered the new designer, declarative XAML workflows, new activities in the base activity library, the flowchart workflow model, hosting of workflows, arguments, variables, and expressions, workflow services, and runtime improvements to name a few things.

The slides and demos for this talk can be downloaded here:   Slides    Demos





Sunday, August 16, 2009 3:47:13 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Tuesday, August 04, 2009

TechEd Africa Sessions and Demos

This week I had the pleasure of speaking at TechEd Africa in Durban South Africa. It was a great venue, great attendees with insightful questions, and generally just a lot of fun to get to see a part of the world I’ve never been to while still teaching people about the cool capabilities of the .NET Framework and the best ways to employ those capabilities.

I did 5 sessions, briefly outlined here:

WUX303: New Tools and Controls for Building Rich WPF Line of Business Apps

The real title was something else, horrendously long and un-pronounceable in one breath, but that covers the gist of it. I showed how to use the DataGrid, DatePicker, and Calendar controls that are available for .NET 3.5 development today with the WPF Toolkit. If there are any WPF developers out there that don’t have that as part of their standard development machine set up after installing VS 2008, they are selling WPF short and hindering the user experience for their user (unless they have a third party control library that gives them similar and more functional versions of those kinds of controls). Those controls will also be incorporated as part of the framework in .NET 4.0, so I also demoed their use in VS 2010 along with the great new data binding features in the designer, which closely mimic the capabilities in Windows Form 2.0 that I covered extensively in my data binding book. I also talked about the new WPF Ribbon control and showed its use, and briefly talked about the MVVM pattern, showed an implementation in the demos, and mentioned the MVVM Toolkit that is in development that will make it easier to do.

SOA305: Exercise WCF Best Practices

In this session, I went through a bunch of best practices for WCF, along with their context, to help people identify practices they should be following regularly when implement WCF services and clients. I covered things like starting your services as PerCall rather than the default of sessionful, exception management on the server and client side, implementing and attaching error handlers, picking a hosting model from IIS, WAS, self-hosting, and eventually Dublin, self-hosting coding patterns, proxy creation and management patterns, and a brief touch on REST vs SOAP at the end. It was a jam packed session and I unfortunately did not have enough time with a 1 hour session to show as many code samples of the practices I was covering as I wanted.

SOA401: Developing Service Oriented Workflows

This was pretty much the same session I gave at TechEd US, with the exception that I had to cut some content and do less coding from scratch because the session here was only an hour vs 1:15 in the states.

 

SOA201: New Features in WCF and WF 4.0

This was a packed session, standing room only, so obviously a lot of people want to know what is coming down the pike. I covered the new features in WCF 4.0 including simplified configuration, Discovery, Router Service, REST features, and a few others. Then I switched to WF 4.0 since the changes are even more sweeping there and covered the new declarative workflow model, data flow with variables and arguments, workflow services and more. Fun session, just wish I could have twice as much time to give all the great new features better coverage.

Whiteboard Session: Are WCF and WF for Mere Mortal Developers?

Had good attendance and some great questions and discussions with the attendees about the barriers to adoption with WF, what are some of the scenarios where you should just not bother with WF, where those scenarios change with WF 4 compared to 3, and what some of the pain points are with WF in terms of adoption. There was also a fair amount of discussion on WCF, talking about challenges and solutions as far as managing configuration of services, diagnostics and tracing capabilities, factoring of service interfaces and moving to WCF from other technologies and architectures.

For those that attended, thanks! For them and others who want the demo code, here is one zip with all session demos in it.





Tuesday, August 04, 2009 4:24:08 PM (GMT Standard Time, UTC+00:00)
Comments [1]  | 


  Thursday, July 23, 2009

Obscure WCF Exception – Mislaid Blame

I lost a couple hours today to perhaps the most obscure WCF error message I have encountered yet. I do tons of WCF and have been working with WCF extensively since 2003 timeframe when I had access to the private betas. I would consider myself a top expert on WCF, and yet this one really was kicking me in the butt. Without a methodical approach to troubleshooting it, I never would have sorted it out.

Most WCF errors, after developing a good experience base with the technology, you can rapidly solve. You will either get to know some common ones and know where to jump in your configuration to sort it out, or you can Bing/Google the error message and you will usually find some forum posts where someone suggests the right configuration fix.

I was putting together a very simple WCF call from a client to a service, using username security with the WsHttpBindiing. When I got everything set up the way I had done hundreds of times before, I was getting an exception whenever I tried to make the method call on the client.

The error I got stuck on was telling me this:

Outer exception: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.

Inner Exception: An error occurred when verifying security for the message.

OK, fine. I’ve seen those many times before. Went back and quadruple checked all my security settings on both the client and server. All seemed well there. Time to search. Lots of people have apparently had this error, and every solution I found had to do with making sure the clock on the client and server were matched up. Hmm, I’m running client and server localhost. I’m no time-space continuum expert, but I’m relatively certain when two parties reference the same clock, they are in sync.

So then it became an exercise in eliminating variables.

Change the service method to return null to eliminate some kind of serialization error. No, not it.

Snap back to a default WsHttpBinding with no modifications. All works well there. Gotta be the binding.

So I look closer at what I had hacked together for a server binding:

<wsHttpBinding>
  <binding name="MyBinding" maxReceivedMessageSize="20000000">
    <security mode="Message">
      <message clientCredentialType="UserName"/>
    </security>
    <!--Remove the readerQuota or increase its size, problem goes away-->
    <readerQuotas maxArrayLength="2000"/>
  </binding>
</wsHttpBinding>

Thanks to the fact that I had just observed a conversation on a connected systems email alias regarding maxBufferSize and why it doesn’t exist on WsHttpBinding, it occurred to me that it could be my (arbitrarily chosen) message size or array length.

Sure enough, if I removed the readerQuotas maxArrayLength altogether, or just bump it up by one extra zero, the problem disappeared. I know that there is some coupling between maxReceivedMessageSize and maxArrayLength, but don’t know the specific rules off the top of my head. But I just wanted to get this out there that if you have those errors indicating security problems and you are convinced your security is configured correctly, try tinkering with your sizes in the binding. That could very well be the cause as it was for me.

 

You can download a sample application that demonstrates the problem here.





Thursday, July 23, 2009 2:44:56 PM (GMT Standard Time, UTC+00:00)
Comments [1]  | 

















January, 2012 (1)
November, 2011 (4)
October, 2011 (1)
September, 2011 (2)
August, 2011 (1)
July, 2011 (1)
May, 2011 (5)
March, 2011 (4)
February, 2011 (2)
January, 2011 (3)
November, 2010 (4)
October, 2010 (1)
September, 2010 (5)
August, 2010 (5)
July, 2010 (6)
June, 2010 (8)
May, 2010 (2)
April, 2010 (2)
January, 2010 (1)
December, 2009 (3)
November, 2009 (2)
October, 2009 (3)
September, 2009 (3)
August, 2009 (2)
July, 2009 (3)
May, 2009 (3)
April, 2009 (2)
March, 2009 (1)
February, 2009 (2)
January, 2009 (2)
December, 2008 (1)
November, 2008 (2)
October, 2008 (5)
September, 2008 (4)
August, 2008 (2)
July, 2008 (1)
June, 2008 (2)
May, 2008 (2)
April, 2008 (3)
February, 2008 (6)
January, 2008 (3)
December, 2007 (1)
November, 2007 (1)
October, 2007 (5)
September, 2007 (1)
July, 2007 (3)
June, 2007 (8)
April, 2007 (2)
March, 2007 (4)
February, 2007 (1)
December, 2006 (2)
November, 2006 (9)
October, 2006 (5)
September, 2006 (3)
August, 2006 (2)
July, 2006 (4)
June, 2006 (5)
May, 2006 (10)
April, 2006 (4)
March, 2006 (2)
February, 2006 (12)
January, 2006 (7)
December, 2005 (2)
November, 2005 (15)
October, 2005 (6)
September, 2005 (7)
August, 2005 (3)
July, 2005 (10)
June, 2005 (11)
May, 2005 (7)
April, 2005 (8)
March, 2005 (6)
February, 2005 (2)
January, 2005 (6)
December, 2004 (3)
November, 2004 (5)
October, 2004 (2)
September, 2004 (5)
August, 2004 (13)
July, 2004 (6)
June, 2004 (14)
May, 2004 (17)
April, 2004 (12)
March, 2004 (8)
February, 2004 (10)
January, 2004 (14)
December, 2003 (9)
November, 2003 (13)
October, 2003 (3)





Sign In
Copyright © 2006-2007 Brian Noyes. All rights reserved.

designed by NUKEATION STUDIOS