ViewModel with MVC/Navigation in Silverlight

This post continues the discussion and investigation into the ViewModel (aka MVVM) pattern. This time around, the sample, a New York Times Newswire API-based News Widget application demonstrates how the MVC pattern caters to implementing navigation logic, while the ViewModel pattern focuses on interaction logic.

I've been writing about ViewModel (aka MVVM) pattern (here, here, here and more) and implementing it in Silverlight.FX for quite some time now, and it continues to be an exciting area for further thinking, and prototyping. This time around I want to cover how ViewModel and MVC fit together in an application at the same time.

I have put together a set of navigation features into Silverlight.FX: a Page base class, a PageFrame control, and a Navigate trigger action. The PageFrame class by default maps URIs to Page types automatically, but at the same time supports plugging in an MVC PageLoader that maps URIs to Controllers and Actions, and maps ActionResults resulting from those actions into visuals or Pages.

Specifically the controller and the action methods enable writing navigation logic that runs in the context of when a view is being loaded as a result of loading a URI. The result of such an action, and navigation, is a Page and its associated view model. The view model on the other hand encapsulates interaction logic, i.e. the commands and operations and associated view state that come into play as the end-user interacts with the UI. Hopefully this post will show both using a sample application.

MVC and View Model

The diagram depicts the different building blocks and their relationships.

The Frame control hosts the pages and loads URIs when navigation occurs. The URI loading is performed by routing requests to Controller and its Actions. The controller performs any navigation logic, and potentially uses the data model and data access layer to load any relevant data as part of executing the action. The resulting ActionResult is mapped to a Page and its associated View Model. The view model contains properties, methods and events to encapsulate view state and interaction logic. The view consumes its view model by virtue of data-binding and commands, and subscribes to view model notifications using event triggers.

New York Times News WidgetThe Sample Application

In order to illustrate the ViewModel pattern working together with navigation and MVC, I've put together a fairly straightforward sample in the form of a News Widget application. This widget allows searching for news articles and listing the latest news articles by using the recently published New York Times Newswire API.

You can run the live sample as well before reading further to get a sense of what the application does, and the navigation functionality at play.

The rest of the blog post builds this application step by step:

  • - Implement the Controllers
  • - Populate the IoC container to fulfill controller dependencies
  • - Implement the corresponding Views
  • - Implement the main window containing the PageFrame and the Navigation Buttons and Search UI

Implementing the Controllers

Controllers are classes that derive from the Controller base class, and are located within a Controllers namespace. They contain Actions, which are public methods that return either ActionResult or Task<ActionResult>. The latter is to support async actions, which is key in the realm of Silverlight, since a controller performing network access to load some data is going to need to do async work behind the scenes.

The News Application Project in Solution ExplorerIn this application, I am going to have two controllers: HomeController and NewsController.

namespace NewsWidget.Controllers {
    public sealed class HomeController : Controller {
        public ActionResult About() {
            return View("About");
        }
    }
}

HomeController is quite basic. It doesn't contain much logic, other than producing a ViewActionResult indicating that the view named "About" must be used to render the result of invoking the controller.

public sealed class NewsController : Controller {
    private INewsService _newsService;

    public Task<ActionResult> List() {
        Task<ActionResult> task = new Task<ActionResult>();
        _newsService.GetNews(/* limitToLastDay */ true,
                             OnNewsItemsAvailable, task);

        return task;
    }

    public Task<ActionResult> Search(string query) {
        if (String.IsNullOrEmpty(query)) {
            throw new ArgumentNullException("query");
        }

        Task<ActionResult> task = new Task<ActionResult>();
        _newsService.Search(query, OnNewsItemsAvailable, task);

        return task;
    }

    private void OnNewsItemsAvailable(IEnumerable<NewsItem> newsItems,
                                      object userState) {
        IEnumerable<NewsItem> orderedItems =
            newsItems.AsQueryable().
            OrderByDescending(i => i.PublishDate);

        ViewActionResult result = View("List");
        result.ViewData["Items"] = orderedItems.ToArray();

        Task<ActionResult> task = (Task<ActionResult>)userState;
        task.Complete(result);
    }
}

The NewsController is more interesting. It has two actions: List and Search. The Search action takes a string parameter. Rather than returning ActionResult, both of these return Task<ActionResult> as they both perform some async work to load news articles. When the async work is completed, they produce a ViewActionResult indicating a view named "List" should be used. The ViewData is populated with the list of news items that were just retrieved.

The controller has basically encapsulated the navigation logic - how latest news articles are retrieved, and how they are searched. Loading of news articles happens as a result of navigation, before a page is loaded into the visual tree. Consequently, the new page is not empty when it first shows up on screen, which makes it possible to transition to it with a visual effect such as cross-fade. It also allows the controller to fail the navigation if there is an error loading the data, or perform a redirect, should something like a login be required. Effectively, introducing the controller pattern allows implementing the logic that is closely associated with navigation in the application separated from the UI itself, rather than putting it into the view model that only gets a chance to do something after navigation to the Page has completed.

You'll notice the use of an INewsService. That is a dependency of the NewsController. At runtime, the NewsController works against an implementation of INewsService that issues web requests to the New York Times Newswire API. This has been factored out and abstracted via an INewsService, so it can be mocked at unit test time, if you'd like to test this Controller in isolation. As such, at runtime I'd like to use IoC to fulfill the dependency (I first described this here). So I'll add the following constructor:

public sealed class NewsController : Controller {
    private INewsService _newsService;

    public NewsController([Dependency] INewsService newsService) {
        _newsService = newsService;
    }
}

I have the following implementation of INewsSerivce:

namespace NewsWidget.Services {

    [Service(typeof(INewsService))]
    public class TimesNewswireService : INewsService {
        ...
    }
}

In my Application, in NewsApplication.xaml, I'll declare the actual implementation of this service, which is used to populate the default container against which dependencies are resolved.

<fxapp:XApplication
  xmlns:fxnav="clr-namespace:SilverlightFX.Applications;assembly=SilverlightFX"
  xmlns:appsvc="clr-namespace:NewsWidget.Services">

  <fxapp:XApplication.Components>
    <appsvc:TimesNewswireService />
  </fxapp:XApplication.Components>

</fxapp:XApplication>

Creating the Views

So now that I have my controllers, its time to implement the views. Views are basically pages, along with a view model if they need one. Again, AboutPage is really simple. It is a page with some static text content:

<fxnav:Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxnav="clr-namespace:SilverlightFX.UserInterface.Navigation;assembly=SilverlightFX"
  x:Class="NewsWidget.Views.Home.AboutPage">

  <TextBlock Text="..." />
  ...

</fxnav:Page>

ListPage is much more interesting. The ListPage displays a list of news articles. It also provides the end user with the ability to filter the list down to those news articles published today. In other words it has some interaction logic. This will be facilitated with a view model. Here is the XAML:

<fxnav:Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  xmlns:fxnav="clr-namespace:SilverlightFX.UserInterface.Navigation;assembly=SilverlightFX"
  x:Class="NewsWidget.Views.News.ListPage"
  ModelType="NewsWidget.Views.News.ListPageModel">
  <fxui:XGrid Rows="*,Auto">
    <fxui:ListView Style="{StaticResource newsItemListStyle}"
      DataSource="{Binding ListItems}">
      <fxui:ListView.ItemTemplate>
        <DataTemplate>
          ...
            <TextBlock Text="{Binding Headline}" TextWrapping="Wrap" />
            <TextBlock Text="{Binding Section}" />
            <TextBlock Text="{Binding Summary}" TextWrapping="Wrap" />
          ...
        </DataTemplate>
      </fxui:ListView.ItemTemplate>
    </fxui:ListView>

    <CheckBox x:Name="filterCheckBox" Grid.Row="1" HorizontalAlignment="Center"
      IsChecked="{Binding FilterToday, Mode=TwoWay}"
      Content="Show only today's news" />
  </fxui:XGrid>
</fxnav:Page>

And here is the corresponding view model, ListPageModel, which is associated with the Page via the ModelType property.

public class ListPageModel : Model {
    private bool _filterToday;

    public bool FilterToday {
        get { return _filterToday; }
        set {
            _filterToday = value;
            RaisePropertyChanged("FilterToday", "ListItems");
        }
    }

    public IEnumerable<NewsItem> Items { get; set; }

    public IEnumerable<NewsItem> ListItems {
        get {
            if (_filterToday == false) {
                return Items;
            }

            return Items.Where(item => item.PublishDate.Date == DateTime.UtcNow.Date);
        }
    }
}

The ViewModel exposes the Items property. This is initialized using the ViewData generated by the controller action (the ViewData dictionary contains an item named "Items" as added by the controller action). It also exposes a ListItems property which is either all the items, or a list of items filtered to the current date. The ListView in the UI is bound to the ListItems property. The filterCheckBox in the UI is two-way bound to the FilterToday property on the ViewModel. This allows toggling the set of items shown in the UI. Together these properties and filtering behavior represent the interaction and interaction logic of the view.

Performing the Navigation

Now that we have our controllers and the views, we need to actually perform navigation and display the pages in the UI of the application. I'll first add a PageFrame, the control that does this, in the main window of the application.

<fxui:Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  xmlns:fxnav="clr-namespace:SilverlightFX.UserInterface.Navigation;assembly=SilverlightFX"
  x:Class="NewsWidget.NewsWindow">

  <fxnav:PageFrame x:Name="mainFrame">
    <fxnav:PageFrame.Loader>
      <fxnav:MvcPageLoader />
    </fxnav:PageFrame.Loader>
    <fxnav:PageFrame.Transition>
      <fxtransition:CrossFade Duration="00:00:0.25" />
    </fxnav:PageFrame.Transition>
  </fxnav:PageFrame>

</fxui:Window>

On the PageFrame, I've replaced the default Loader (which maps URIs to Pages directly) to instead use an MvcPageLoader. The MvcPageLoader understands the MVC pattern. Specifically it does two things. First it performs routing. It resolves a URI into a Controller type and an associated action (along with action parameters), and then invokes the action. Secondly, it processes the resulting ActionResult from the control to perform the work of a view engine to produce a Page visual.

The MvcPageLoader in Silverlight.FX contains a few conventions. URIs are of the form: /ControllerName/ActionName/[PathContainingPositionalParameters]?[QueryStringWithNamedParameters] Optionally if there is only one Controller in the application, the ControllerType can be specified on the MvcPageLoader and that simplifies the URI to: /ActionName/[PathContainingPositionalParameters]?[QueryStringWithNamedParameters]

Controllers are looked up in a Controllers namespace by appending the "Controller" suffix to the name. Views are located within a subnamespace named after the Controller name within a Views namespace of the application. For example, the "About" view referred by the HomeController is a page, AboutPage, defined in the Home subfolder within the Views folder. Similarly the "List" view referred by the NewsController is a page, ListPage, defined in the News subfolder within the Views folder. This can be seen in the project structure as shown in the Solution Explorer screenshot above.

Today the only view engine logic has the MvcPageLoader looking up Pages corresponding to a ViewActionResult. In the future I'll be extending it to look for DataTemplates for an ObjectActionResult.

As an aside, PageFrame also supports page-to-page transitions, and I've specified that I want to use a cross-fade effect for this particular application.

Now I need the links themselves. Here are couple of buttons in the main window of the application:

<Button Content="Latest News" Style="{StaticResource linkButton}">
  <fxui:Interaction.Triggers>
    <fxui:EventTrigger EventName="Click">
      <fxaction:Navigate Target="mainFrame"
        NavigateUrl="/News/List" />
    </fxui:EventTrigger>
  </fxui:Interaction.Triggers>
</Button>

<Button Content="About" Style="{StaticResource linkButton}">
  <fxui:Interaction.Triggers>
    <fxui:EventTrigger EventName="Click">
      <fxaction:Navigate Target="mainFrame"
        NavigateUrl="/Home/About" />
    </fxui:EventTrigger>
  </fxui:Interaction.Triggers>
</Button>

As you can see I've used a Navigate trigger action to cause navigation to occur when a Button is clicked. The Navigate trigger action can be associated with any event of any control... so I could also have had an image as my navigation UI and perform navigation in response to the MouseLeftButtonDown event.

The Search functionality is a bit more interesting. Here the view model associated with the main window itself plays a role. Here is the XAML for the search UI:

<fxnav:Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  xmlns:fxnav="clr-namespace:SilverlightFX.UserInterface.Navigation;assembly=SilverlightFX"
  x:Class="NewsWidget.Views.News.ListPage"
  ModelType="NewsWidget.Views.News.ListPageModel">

  <TextBox x:Name="searchTextBox" Width="140" Text="{Binding SearchText, Mode=TwoWay}">
    <fxui:Interaction.Behaviors>
      <fxui:AutoCommit ButtonName="searchButton" />
    </fxui:Interaction.Behaviors>
  </TextBox>

  <Button x:Name="searchButton" Content="Search" Style="{StaticResource linkButton}">
    <fxui:Interaction.Triggers>
      <fxui:EventTrigger EventName="Click">
        <fxaction:Navigate Target="mainFrame"
          NavigateUrl="{Binding SearchUrl}" />
      </fxui:EventTrigger>
    </fxui:Interaction.Triggers>
  </Button>

</fxnav:Page>

Here is the associated view model:

public sealed class NewsWindowModel : Model {
    private string _searchText;

    public string SearchText {
        get { return _searchText; }
        set {
            _searchText = value;
            RaisePropertyChanged("SearchText", "SearchUrl");
        }
    }

    public string SearchUrl {
        get {
            if (String.IsNullOrEmpty(_searchText)) {
                return null;
            }
            return "/News/Search?query=" + _searchText;
        }
    }
}

In the UI, the Search TextBox is two-way bound to the SearchText property. Whenever the SearchText property is changed, the SearchUrl, a computed property is also changed. The Navigate trigger action in the UI has its NavigateUrl property bound to SearchUrl. So when the user clicks the Search button in the UI, the computed SearchUrl is used to perform the navigation.

So again what you see is the view model facilitating interaction logic. Specifically it encapsulates the logic of building a URL to the Search action on the controller in response to the user entering in some keywords to search for in the SearchTextBox.

Summary

This application shows how both MVC and ViewModel (aka MVVM) co-exist in a single application.

The MVC pattern enables writing navigation-oriented logic in the form of a set of synchronous or asynchronous action methods that produce corresponding ActionResults. The ViewModel pattern allows writing interaction logic in the form of properties representing view state, methods representing operations and events (not shown here) representing notifications.

Both patterns are common from the perspective that they allow separating logic out from the UI, so they can be written and tested in isolation. Both can contain dependencies that need to be fulfilled via an IoC container and dependency injection.

The sample is part of Silverlight.FX. You can download the framework sources, the sample sources (along with several other samples), and the framework binaries. You can follow further development on the project page or at its associated GitHub repository. Aside: While all this should work in Silverlight 3 as well, I have started porting Silverlight.FX to Silverlight 3 to make use of some new capabilities, and hope to have that version ready soon.

Hope you found this interesting even though its a bit on the long side. I'd love to hear your thoughts and suggesstions on the pattern, as well as the implementation in Silverlight.FX.

Posted on Saturday, 5/30/2009 @ 9:13 AM | #Silverlight


Comments

24 comments have been posted.

Steve

Posted on 5/30/2009 @ 8:58 PM
Nikhil, can I ask why Silverlight 3 isn't baking some of this richness into the framework ?

I just just think this is critical stuff for making Silverlight a product to be taken seriously - your combining a best practices infrastructure that imo should be in Silverlight 3 !

MS should have you on the Silverlight team if you aren't already :)

I'm dying to see Blend support for your custom controls as well :)

Thanks for the post.

Nikhil Kothari

Posted on 5/30/2009 @ 9:51 PM
@Steve - I am an architect on the broader Silverlight team that comprises of core runtime and frameworks on top of that. So a lot of this is in fact prototyping and early thinking to facilitate fleshing out ideas.

There is an element of time. Silverlight 3 is pretty much feature complete. However, a lot of discussions are happening for Silverlight 4, where some of these concepts will likely make their way into the built-in framework. In some sense the process is already happening - for example the behaviors feature in Silverlight.FX made its way into the Blend behaviors API, and I believe the two APIs are almost identical if not 100% the same.

Also there is an element of what is core vs. not. What has to go into the core is fundamental infrastructure, and there are things like markup extensions, amongst others that need to find their way into the platform to further simplify higher level building blocks. The higher level building blocks however do not absolutely need to be in core... they can be transparent frameworks/libraries. With patterns, this is even more so the case. Multiple possible implementations are possible on top of the same general pattern, each one a valid approach in its own right. This just suggests, we need to be careful what to bake into the core, vs. what is logically in a layer above, whether its supplied by MS, or by some 3rd party.

If there are things you like in particular, I'd recommend voicing those opinions, and making those suggestions. Customer feedback counts a lot in trying to get these ideas incorporated into a larger product.

Steve

Posted on 5/31/2009 @ 6:30 AM
Thanks - just keep up the good work. And I have sent emails with suggestions, based on real world examples to some others (Abrams, etc...) - and I'm seeing good responses etc...

I agree on core - let me give one example of how I think Silverlight designer/Blend could really help this particular project, basically rather than 'change the core', it would be 'make the core more able to work with custom control like you have built' :

ie. You've created these custom controls - building on top of core Silverlight controls - right ? Let's compare this to create your own .NET ASP.NET control (I have your book...hehe) - and you build a designer piece for the control. That makes the control easier to work with. Yes, you can set all the properties in code, etc... without it, but it makes a huge difference, especially in a shop of 10+ developers using these controls. Fast forward that to your window control. Yes, I can use your grid layouts - which I prefer over base SL layouts - however, I'm forced to 'build, run, adjust. adjust layout, build, run, view. etc...' - this is where VS designer/Blend designer needs to recognize your control and allow for designer support. I should be able to open Blend. Point to your Silverlight FX library - it should be able to extract out all controls built on base SL controls and add them to the controls library. Then we need designer support for those controls. This isn't changing Silverlight core- it's providing a good foundation in which developers can quickly create their own controls like you have - does that make sense ? ('m assuming here in VS 2010 and the next Blend that they are aware of these situation - if not, they need to be !!!

So the first thing I would do is hand your controls to the 2010 team and Blend team and say 'here is an example of custom controls, how can we get the tools to recognize these controls' - not 'add them to the core' but 'make the designers work well with them'

That was probably my only issue with building a prototype FX app - I liked all the controls and the architecture but was constantly trying to adjust the view to make it what I needed. More designer support for the controls would help.

I like what your doing - right now in the marketplace this is what I'm seeing: many companies that want to use Silverlight have custom DAL layers. They aren't using EF or Linq yet. And when I go there to do work, one of the first things I'm going to look at is

(1) can RIA.NET bridge that gap - that to me is extremely important. Not many shops I have worked at pass their entities to the UI. Typically they have DTO and Mappers. So I think RIA.NET needs to be thinking in terms of being the glue of communication to those layers to the UI. I know (or think I do) that this is the direction of RIA.NET. ie. I'm going to have a 'client object' with 'data annotations' that is mapped in from a domain object or some data layer (even a dataset) to this object. This object will be used in the Silverlight UI. A unit of work will track changes and send them back asychronously to this repository layer -> to a dal layer., etc...
(2) then sitting on top of that is your Silverlight.FX framework, abstracting out navigation, pages, windows, progress bars, even hopefully dynamically loading xap's to make for a smaller initial footprint, all using a good MVC/MVVM architecture.

Your efforts certainly aren't going unnoticed by me - I think your leading a charge that I hope catches on - thanks again, and I'll be deeply exploring this sample. (And I appreciate taking feedback like you do).

I encourage you to talk to the devs making the designers and see how those tools can incorporate 3rd party controls such as what you have created here.

Steve

Posted on 5/31/2009 @ 6:35 AM
I left one part out of the #1 above- companies that already have service layers with messages from WCF is common.

So, seeing RIA.NET work with a WCF endpoint to 'consume' that service and pick up that message/proxy is a good step as well - in other words consuming DTO objects that later are associated behind those services to an entity/domain object or even direct SP call.

Rob

Posted on 5/31/2009 @ 12:38 PM
First of all, very interesting approach. However, Microsoft should be spending their time getting the core architecture and features right. Let the OSS community build this type of framework. OSS has shown time and time again that they are the only ones with the experience in how to build a high-level framework properly. Every time MS tries, they blunder. Microsoft's strength is in low-level platforms and frameworks, not in high-level application frameworks. If Microsoft wants to gain the experience of the OSS community with regards to high-level frameworks, then they need to take every SL dev off the project and distribute them in the field building real applications (of all sorts, not trivial demos) on top of their framework. Make them go from design to production. Make them write unit tests. Then, make them do a v2 of their app, forcing them to maintain what they had built and extend it. After this, bring them back and start designs on a high-level SL framework. They will have some understanding at that point because they will be able to "extract a framework" out of the applications they built. However, they would have to follow this pattern for several years in order to gain the collective knowledge/experience of the OSS community. This is obviously impractical, so why doesn't Microsoft just let OSS handle it? For example, there is already a very powerful routing based Silverlight framework called nRoute. Why does Microsoft need to build something similar to what OSS has already built, but with a poorer and less experience-hardened implementation? We (the OSS community) have aready built the frameworks, built them better and have tested them in the wild on real applications. Why is Microsoft always fighting us?

Second, I would cry tears of utter dismay if something like this was part of the Silverlight core or even part of the standard .dlls. If you are bent on building a high-level framework, then distribute it separately. And for the love of all things sacred, do not ever force me to build Silverlight/WPF applications like this. Routing-based architectures work for a very specific class of applications. Many desktop applications would not make sense with this type of architecture. In fact it would greatly complicate them if they were forced into this mold. It makes
the same fundamental mistake that the ASP.NET team made when they designed WebForms; they took the web and tried to make it look like a windows application. Routing-based desktop applications try and make the desktop look like the web! It works to your advantage only in a very specific class of applications, but not all. In reality there are several different approaches to building applications, navigation-based being one. Is Microsoft going to build a framework for every type of UI application architecture? I think not. But, OSS can, and pretty much already has. So why not help us instead of trying to steam-roll over us?

Please don't take any of this personally. But I get angry when I see that Microsoft is not leveraging their true strengths and in the process hurting others who really do have unique strengths and experience which Microsoft does not have.

Mike Brown

Posted on 5/31/2009 @ 5:02 PM
@Rob seriously? Most OSS frameworks are either stepchildren of Java frameworks that don't take advantage of the capabilities of .NET or are so abstract and complicated that by the time you understand what they do, you could have written your own version from scratch. Yes I know there are exceptions that's why I said most.

@Nikhil, I think your pattern is more Front Controller w/view model instead of MVC and view model. Otherwise I think it's a very good and natural combination.

Jakob

Posted on 5/31/2009 @ 5:43 PM
I would love to see this as a part of Silverlight. As templates, assemblies, demos, articles, videos, even opensource, all to get you started right on a project. I do not see any opensource pattern work in relation to Silverlight yet. If Microsoft could kick start and spread the different patterns suited to Silverlight / WPF this would be great. This is what the above article does, give us more of that.

Rob

Posted on 5/31/2009 @ 8:52 PM
@Jacob
There are several OSS frameworks for Silverlight. My own framework, Caliburn, has been around for over 2 years. It was first built for WPF and then re-architected to compile for SL. So, it's a consistent framework for both platforms. It was extracted from real applications that are in production now. As, I mentioned in my comment, there's also nRoute. Furthermore there is Fluent Silverlight, Silverlight Nav Effects, Silverlight-Palladium Framework and Onyx. Let's not forget Prism either. That makes SEVEN OSS frameworks for Silverlight! There's also Contrib projects for both Prism and Caliburn. There are probably more frameworks, too. It took about 10 seconds of search on google/codeplex to find these.

@Mike
Not sure what you are referring to. My entire stack is OSS and only one component comes out of the Java world, and that is NHibernate. NHibernate takes significant advantage of .NET and has surpassed it's Java counterpart. The present version is quite easy to use because of Fluent NHibernate and NHibernate.Linq. All in all, it's much more feature rich and IMHO easier to use that EF. An no, I can't write my own version of NHibernate easier than I could learn it and the same goes for all of the frameworks I use (except for the one I wrote:). You can check out my OSS stack here: https://www.ohloh.net/stacks/26578 I haven't had much trouble learning these frameworks. All in all, I've spent more time fighting with ASP.NET and WCF then I ever have with an OSS framework. Perhaps it's time you take another look?

Rob

Posted on 5/31/2009 @ 11:00 PM
I was thinking a bit. I definitely overreacted in my first comment above. One of my shortcomings is that I tend to be a bit manic concerning Microsoft frameworks, particularly when they overlap OSS efforts. I apologize if I came off as rude or self-righteous. Nikhil, you have done a lot of great work in Silverlight.FX and don't want to downplay it or the efforts your are making to address real issues. In reality, I have two main concerns and I'll try and express them with my head on instead of exploding in a rant like before (again my sincere apologies).
First is that the Silverlight team may not be the best group to address this problem. They are very talented and highly skilled and I have been very impressed with what they have been able to build into Silverlight, especially given the relatively short time frame. However, where there skills lie is not in building application frameworks, but in building platforms. They can get the CLR to run on Mac. They can get hardware accelerated, vector graphics working cross platform, etc. But it takes developers who have been using Silverlight/WPF for years, building a large variety of applications, coming together, before you can arrive at a strong application framework. The Silverlight team just isn't the right group to do this. They can certainly help, by adding platform hooks that may be needed by higher-level components. But, they shouldn't be the ones building those high-level pieces. One of the reasons that the ASP.NET MVC framework has such a strong foundation is because several of the key developers came out of the real world, with real problems fresh on their mind that they were trying to address. The MVC framework was also rigorously critiqued by a very mature community, many of whom were OSS contributors. Such a community does not yet exist for Silverlight. If anything, its too earlier for Microsoft to prescribe "best practices" to Silverlight development, and they certainly should not do it without extensive involvement from the community.
My second concern is a strongly held personal opinion regarding your MVC implementation. I've put two ASP.NET MVC apps in production (and more using Monorail before that), so I'm aware that you are purposefully trying to match the MVC framework's API. It seems like a good idea on the surface. However, when you build a silverlight application, you are not building a web app, you are actually building a desktop application. As such, using a FrontController will only work for simple, navigation-oriented scenarios, which are not what most desktop applications are. If you have a more complex solution that needs navigation, this won't cut it. You will have to go with something like nRoute. Or you could take a different approach altogether wtih Caliburn. I think its a neat idea, don't get me wrong. But the truth is that you have to choose an application framework based on the type of application you are building. Since there are many types of applications, it stands to reason that there could be many types of application frameworks. Again, this is a demand that only OSS can meet. The .NET Framework is already too big, and it is my opinion that this is because OSS has not been embraced by Microsoft. Instead, they have tried to build everything and the kitchen sink into the platform. With Silverlight, we have a chance to learn from the mistakes of the past. It's a small, manageable version of the .NET Framework once again. Let's be really careful what we do with it.

Nikhil Kothari

Posted on 6/2/2009 @ 12:09 AM
Great discussion folks.
@Rob, I hear your concerns. Let me address some of it, or perhaps share my opinions.

I agree, you need application building experience and application framework experience, and not just platform building experience to target this space. Its a competency that needs to be developed or polished, or extended to client apps where traditionally it might have existed in the context of web/server apps. Note that the broad Silverlight team consists of folks working on graphics, lower-level capabilities, as well as controls, and also higher level application frameworks (eg. .NET RIA Services).

I think Microsoft needs to get into this - so it offers not just low-level building blocks, but rather solutions to real problems, because that is what the community is increasingly asking for, and that is where true productivity lies. We not only need to get some broadly applicable solutions in place, but get them mainstream, and provide tooling for them. I don't think the claim (at least from me) is that there is one right solution, and one size fits all. There will be alternatives, and over time different frameworks will learn from each other, and evolve... sometimes continue to co-exist, sometimes converge etc. I think it would be helpful for the OSS community as you call it, not just come forth with solutions, but scenarios, requirements, feedback, so as to help in this space. All too often I see increasingly specific solutions proposed, when reality is someone like Microsoft needs to balance several things at once when coming up with a solution.

Indeed the goal is to avoid the kitchen-sink, but instead be more targeted, and prescriptive, and small, etc. other virtues that apply in this space such as testability and simplicity.

Perhaps this is a front controller pattern. Potentially this is a naming issue. I chose MVC, because I think the familiarity with the name helps. I do not actually think this would replicate the asp.net one... it catered at a smaller subset of navigation scenarios, since there are additional things like view model that complete the picture.

As always, I'd welcome any feedback folks have ... as we're indeed in early planning and thinking phases for these class of features and framework bits.

Rob

Posted on 6/2/2009 @ 6:49 AM
Nikhil, you have restated my exact concern: "the broad Silverlight team consists of folks working on graphics, lower-level capabilities, as well as controls, and also higher level application frameworks (eg. .NET RIA Services)." What's critically missing from this list of things the SL team is working on? Applications. No one building these frameworks is building *real* applications. It's pretty much impossible to get a high-level framework (like RIA services or anything else) right, without having a host of WPF/SL applications that you have built and put in production to draw from. Frameworks should be extracted from applications, not created ex nihilo. This is something that OSS can do much better than Microsoft. I'd like to see Microsoft recognize this and use it to their advantage one of these days.

Steve

Posted on 6/2/2009 @ 4:10 PM
I would have to agree with this.

ie. I've sent some ideas to Brad Abrams and some from RIA.NET team. I like the 'DomainService' approach however, there are certain items in it that wouldn't really fly with a team in an action project - for example the automatic code generation into the silverlight app. I'd rather see something more like what we get with a web/wcf service where you add in your 'domain service reference' and it create the proxies by updating those references.

The concept of the RIA is, IMO, a great direction and I'm glad to see it - and by taking some real world input it will help build a framework that we can use.

What I see in SilverlightFX is a thought out approach in 'how would I build an application with silverlight' - with transitions, navigation, windows, controls - DI, etc... not too much different than perhaps what Prism is doing. I have experimented with Caliburn as well. Some of it started by looking at obvious deficiencies in the Silverlight framework that Caliburn, SilverlightFX provide.

I definitely think it's ok for MS to create a framework with tools to help build on top of that framework. These OSS projects to me are attempts to take the framework and provide a best practice architecture on top of it. These are application architecture tools - Caliburn, SilverlightFX, Prism, etc... which sit on top of the Silverlight framework. And again, some of these tools are filling missing gaps in the framework. Hopefully by Nikhil building these, as well as you Rob, that you can goto the framework team and recommend places where you feel the framework should be covering an item instead of your application architecture pieces.

Also, some of the topics I brought up above- the Blend team should see the custom controls that Nikhil has built and say 'how can we integrate user built controls into our tool'. I'm not saying put those control INTO the Blend software - but rather their software should support custom controls and not just throw exceptions or error message about how it can't read the control (which in most cases is just building on the base controls).

So, I agree with what your saying - I know I would many times rather be building and driving my business needs and apps without needing to re-invent an architecture with every project. Being able to use the tools that people like you and Nikhil are building will help drive out more stable applications that share common programming concepts - ie. DI, MVVM, etc...

Nikhil Kothari

Posted on 6/2/2009 @ 8:16 PM
@Rob,
Yes, I agree - I am pushing them team to take the app-building to the next level... specifically make them realistic, engage with the community to not only get feedback on the framework, but feedback, suggestions and validations on the apps themselves.

We do expect real developers with real projects will build real apps and provide feedback that we incorporate. We work with both internal and external developers from this perspective. In some sense this is no different than in the past - we need similar interaction with all of the frameworks and tools we produce. In the case of .NET RIA Services, Silverlight app frameworks this does go to a whole new level, as not only are we being a bit more prescriptive, but there are lots of folks in the community building similar solutions and we need to incorporate those experiences and learnings, and we ourselves are indeed learning as we go along.

I look at the ASP.NET MVC work as one example of successful interaction and partnership with the community of developers working on similar frameworks, and building real apps. We need to do more of the same... and go further from there.

Brig Lamoreaux

Posted on 6/3/2009 @ 8:10 AM
This is completely off topic and sounds like a joke, but, what tool did you use for your diagram?

Nikhil Kothari

Posted on 6/3/2009 @ 2:00 PM
@Brig
I use powerpoint for creating these sort of diagrams.

matma

Posted on 6/8/2009 @ 7:37 AM
Hi Nikhil,
How can I navigate from one page to another? <fxaction:Navigate Target="mainFrame" NavigateUrl="/Home/About" ExternalNavigation="False" /> from inside of page doesn't work. Could You prepare some example?

Nikhil Kothari

Posted on 6/8/2009 @ 10:31 AM
@matma
You shouldn't specify Target if you're inside a page and want the containing frame to navigate. The Navigate action should look for a PageFrame in its visual tree hierarchy if target isn't specified.

Jack Addington

Posted on 6/18/2009 @ 8:35 AM
Hi Nikhil,

Could you post an example of how to use the redirect? Specifically I'm putting a check in my mainWindow controller to check if the user has signed in. If they haven't then I want to poppup the login box and then continue with what I was doing. It isn't quite clear to me how I can do that generically so that any action that hits the MainWindow controller will do my 'IsLogin' check.

Thanks

jack

Sebastijan Pistotnik

Posted on 7/1/2009 @ 4:03 PM
Hi Nikhil,
When I set NewsWidget.aspx as a start up page and click Run Debug in VS 2008, I get an exception:
" at SilverlightFX.UserInterface.Navigation.PageLoader.CreatePage(Object data)"
"The specified URL does not resolve to a Page."
What is the problem? I entered the timesNewswireApiKey which I got at http://developer.nytimes.com... But for example flickr tiles normaly works and can be debuged.

Sebastijan Pistotnik

Posted on 7/1/2009 @ 4:10 PM
Hi Nikhil,
When I set NewsWidget.aspx as a start up page and click Run Debug in VS 2008, I get an exception:
" at SilverlightFX.UserInterface.Navigation.PageLoader.CreatePage(Object data)"
"The specified URL does not resolve to a Page."
What is the problem? I entered the timesNewswireApiKey which I got at http://developer.nytimes.com... But for example flickr tiles normaly works and can be debuged.

Dan Skrekovski

Posted on 7/8/2009 @ 5:17 PM
Hi,

Since you probably do not have time to answer to your sample applications exceptions questions, here is a small architectual one.
You put your data/DataAccess classes (Order, Product etc) into "Silverlight Class Library" and not in "Class Library".
Now all real life applications most probably use its data also from web and windows forms applications, so their data
classes are in "Class Library". But since you cannot add a non silverlight project ("Class Library") to silverlight application project,
your project arhitecture is somehow questionable for real life/practical applications. Is there a reason for you to did it so and why?

Thanks
Dan

Anand Subramanian

Posted on 8/14/2009 @ 1:30 PM
Nikhil,

I am trying to implement the MVC/MVVM model of yours and am stuck at a certain point. My LoginPage.xaml calls an action ProcessLogin in my LoginViewModel.cs, which does the required validation and then navigates to Process action of LoginController. At this point when I am passing this, is the only way for username/password to get back is as string in the Url? When the object to pass to persist becomes larger, like a full profile with address and so on, can I somehow pass the model/viewmodel to be accessed in the controller?

I can see that while creating a view, the model is accessible and we can assign values to it, but my question pertains to when a view is navigating to an action with lots of data, what is the approach to achieve it?

Thanks in advance

-- Anand

Clement

Posted on 9/17/2009 @ 10:43 PM
Very neat. I wonder how this fits with the current SL3 navigation framework. I don't think it supports MVC but it supports URI mapping, which I believe is currently missing in Silverlight FX.

Nikhil Kothari

Posted on 9/21/2009 @ 2:44 PM
@Anand
This is a good question... I think for cases where you have to do some processing with lots of data, that should go into a view model rather than a controller. Then the view model raises a navigation notification, which causes the navigation. The navigation itself is always expressed as a URI, rather than holding lots of state. This is because navigations show up in the browser history (and consequently as bookmarks), so you can't really put a lot of state in them anyway.

@Clement
Basically I made a simplifying assumption in Silverlight.FX - that you don't really need a URI mapping layer if you're good with a couple of conventions... URIs are always /action/querystring if you have just one controller in your app, or /controller/action/querystring if you have multiple controllers. In the future, when I add support for this, if you have controllers across multiple assemblies/packages the convention would become /package/controller/action/querystring.
Post your comment and continue the discussion.