Rants Tagged with “Silverlight”

<<  <  1  2  3  4  5  6  7  8  9  10  11  +  >  >>  (Total Pages: 23/Total Results: 225)

"Which Data Access Should I Use for Silverlight 3?"

Silverlight Logo

It all depends...

 

 

 

Back from DevLink 2009!

DevLink

I had a great time at DevLink this year. Met up with lots of great heartland folks and had some really interesting conversations (about Ruby and F# specifically). If you missed DevLink this year, you missed a great conference. John Keller and company put on a great show (for only $100 conference fee). The .NET Rocks panel at the end of the three days capped off a great few days in Nashville.

While I was charming my way through Nashville, I got around to actually giving a couple of talks at the event.  The code and slides for my MVVM and Blend talks is now available on my Talks page here:

http://wildermuth.com/talks#DevLink_2009

 

RIA Services, Silverlight and MVVM

Silverlight Logo

I've finally had a chance to take a look at the July CTP of RIA Services. My opinion is mixed, but its still pretty early. I ran through the simple walkthrough and it was easy to set up but it still felt as if there is too much Visual Studio magic (a complaint I've had for a long time now).

A Brief Overview

For the uninitiated let me explain a couple of things (though, please don't assume this blog entry is an introduction to RIA Services):

RIA Services is trying to share logic with the Silverlight client. That's the big story (IMHO). Some of this logic is a surface to query, validation attributes and outright code in other cases. Its trying to solve a difficult problem, but they've made a fundamental mistake in my book: RIA Services requires that all pieces are in a single solution file. But why? The magic is code generation.  

RIA Services starts with a Domain class which normally uses a model (Entity Framework or others) to expose the data.  As you change the domain class and the entities, RIA Services builds a code generated file in the Silverlight project (or other client files) for you:

The RIA Magic

As the GameDomain file and the GameModel's entities are changed, the generated code is regenerated to keep up with the changes.

Why This is Troubling

This makes sense in one case because as the domain and entities are changed, the code magically stays updated.  Which is a better experience than updating a Service Reference.  But it requires something called a RIA Link.  This link is between a client-side component (typically a Silverlight application) and a server-side component (typically an ASP.NET Web Site/Project).

The cost of this approach is that the projects must exist in the same solution file. This works for demo's and small projects, but in the big world of enterprise or Internet development this breaks down. Throw in composition strategies (like Prism solves) and it complicates it quite a lot.  I certainly hope that when it reaches 1.0 they'll have a solution for this. The current solution for this is to wrap the domain service with an ADO.NET Data Service, but that means there are two layers to go through instead of one and if that's the approach, just use ADO.NET Data Service instead, right?

Another Concern

While reading the well-written and lengthy overview on RIA Services (that comes with the RIA Services CTP) I noticed that RIA Services comes with a data source object (called DomainDataSource) that can be used directly within XAML to communicate with the domain class:

RIA Services Data Source

If you've been reading this blog for any length of time, you'll know that I think that data source objects are almost always evil in that they suggest that its ok to include data access in the user interface.  And the depth of interaction with the data source is really troubling here.

So What About RIA Services in MVVM?

My first thought was how this impact the best-practices of not co-minging UI and data.  I thought it might not work at all, but as often happens in these cases, the example isn't the exemplar that I can suggest.  The framework (aside from my concern about the solution file) actually allows this pretty easily.

So I went back and grabbed my MVVM example from my MSDN article (seen here: http://msdn.microsoft.com/en-us/magazine/dd458800.aspx) and refactored it to use RIA Services. The breakdown of that architecture was pretty simple:

MVVM Architecture

Notice I am using a RIA Domain Service on the server to expose the data model (instead of ADO.NET Data Services). This is broken up in the solution as a set of client-side projects and server-side projects:

RIA Services Project Breakdown

Notice that while in the typcial scenario (and walkthrough's) the RIA Link is betwen the Silverlight application and the web project, RIA Services allows you to have that link between separated parts of the solution. In this case, we have a MVVM.Data library that contains the entity model and the domain service class.  This allows us to re-use this in separate web projects (which is something that is harder to do in ADO.NET Data Services). We also have a MVVM.Client.Data Silverlight library that contains the model for the Silverlight application (and separates the access to the services so the client does not need to change).

The refactoring was fairly painless in that the entity types that were created with the generated code were identical to the data contract classes created by the ADO.NET Data Services - Service Reference class. I had to change the namespaces but the rest was identical.

In the model class I had to change how I was performing the queries, but the major change there was using the extension method syntax for the query instead of the LINQ syntax. The separation of the Model meant that the refactoring was simple (as the whole pattern is supposed to do).

public void GetGamesByGenre(string genre)
{
  // Get all the games ordered by release date
  var qry = Context.GetGamesQuery()
    .Where(g => g.Genre.ToLower() == genre.ToLower())     
    .OrderByDescending(g => g.ReleaseDate)
    .Take(MAX_RESULTS);

  ExecuteGameQuery(qry);
}

I do wish that the RIA Services style wasn't so RPC (Remote Procedure Call) but that may be because I see the value in client-side LINQ queries instead of "GetGamesQuery()" and such. I think the syntax could be a lot simpler.

Overall, I think that RIA Services can help solve some problems but the bottom line is still too much Visual Studio magic for my taste and the validation is still only covering the very simple cases. Rich validation is always going to be hard (read Rocky Lhotka's book if you don't believe me).

If you want to play with it, you can grab the code here:

http://wildermuth.com/downloads/MVVMExample_RIA.zip

What do you think?

Securing Web Services (Even with OOB)

Silverlight Logo

I was trading tweets today with @pauliom about whether RIA Services would solve some Auth problems he was having out of the browser.  While RIA does do some interesting things with roles/users, I mentioned that typical Forms Auth out of the box should just work.

To that end I have created a simple example of how to protected WCF Services with Forms Auth (works with ADO.NET Data Services as well BTW).  Because I wanted to support it out of the browser as well, I used the new Forms Auth service.  To do so, just add a new .svc file to your project and put this in the body:

<%@ ServiceHost Language="C#"
            Service="System.Web.ApplicationServices.AuthenticationService" %>

 The web.config also needs to know about the service.  So first, add a web extensions like so:

<system.web.extensions>
  <scripting>
    <webServices>
      <authenticationService enabled="true"/>
    </webServices>
  </scripting>
</system.web.extensions>

 Finally, the WCF configuration bits:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior 
          name="OutOfBrowserFormsAuth.Web.AuthServiceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service 
        behaviorConfiguration="OutOfBrowserFormsAuth.Web.AuthServiceBehavior"
             name="System.Web.ApplicationServices.AuthenticationService">
      <endpoint address=""
            binding="basicHttpBinding"
            contract="System.Web.ApplicationServices.AuthenticationService" />
      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
    </service>
  </services>
</system.serviceModel>

Once you have all those pieces you can create the proxy like any other service (with "Add Service Reference...").  Then you can login from the Silverlight application:

var authSvc = new AuthenticationServiceClient();
authSvc.LoginCompleted += (s, a) =>
  {
    if (a.Error != null)
    {
      result.Items.Add(string.Concat("Error logging in: ", a.Error.Message));
    }
    else
    {
      result.Items.Add(string.Concat("Login: ", a.Result));
    }
  };
authSvc.LoginAsync("swildermuth", "P@ssw0rd", null, false);

So securing the web service becomes pretty simple.  I created a new "Silverlight WCF Service" inside a secure folder:

Protected Web Service

I created the web service and then the Service Reference before enabling security so adding a Service Reference would work. This is the one pain point in that you must disable the folder security to add the reference then re-enable it afterwards:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <authorization>
      <deny users="?"/>
      <allow users="*"/>
    </authorization>
  </system.web>
</configuration>

Now the web service will only work once the login happens.  You can test this in or out of the browser and with both stacks with the source code.  Here's a quick screenshot showing it working after login and not working after logout:

Screenshot

 You can download the source code here:

http://wildermuth.com/downloads/ProtectedWCF.zip

UPDATE: Here are some links to the actual docs for this:

Configuring the Authentication Service:

 

RIA Services - Still Not Baked Yet

Silverlight LogoAs regular readers of my blog know (RIA Services Concerns Squashed), I have been a lukewarm supporter of RIA Services for Silverlight. As many of you know, Brad Abrams and company have come through with their latest release (RIA Services Preview July '09) with lots of changes I've been hoping for. Honestly I haven't had time to look at the new build (probably this weekend), but I am hopeful of its overall direction. I am still somewhat tentitive about some of the basic behavior of the framework but I will hold my tongue until I have more time to dive deeper into the code. 

What really concerns me is that I've talked to students and others and many are opting to building systems with RIA Services right now.  This only concerns me because RIA Services is not part of Silverlight 3 and is not released.  Actually, the July version is a "Preview" (something like a CTP) which means they haven't even reached Beta with RIA Services.  Now many these developers are working on very long time lines and can wait until RIA Services releases, but while investigating it makes a lot of sense (and I encourage everyone do that), building production code against a framework that is still in transition is a risky venture in my opinion. 

I am curious who out there is using RIA Services in production systems that will ship this year.  Could you comment on the blog with whether you're using it for an upcoming project?

See Carl and I Talk about Behaviors on DNR-TV!

Silverlight Logo

Recently while in Vancouver for DevTeach, I sat down with Carl Franklin and recorded a couple of DNR-TV episodes.  The first one is on Behaviors (and how to write them). If you're interested in Silverlight, Blend or Behaviors...head over the DNR-TV site and take a look.

http://dnrtv.com/default.aspx?ShowID=144

Prism's Plugin Architecture

Architecture

I was with a client recently and we were looking at refactoring some of their system to use Prism. This client had created a lot of infrastructure to do what Prism does (before Prism was released for Silverlight) that they wanted to opt into using Prism instead.

Out of the box Prism works well for composing your applications, but for particular cases it may not be perfect. In this case the client wanted to be able to process the .xap file before it was passed onto to the module loader. So looking through Prism's Modularity code and found that IModuleManager interface. In order to provide my own implementation I wrote a simple implementation of the interface:

public class CustomModuleManager : ModuleManager
{
  IEnumerable<IModuleTypeLoader> typeLoaders;

  public CustomModuleManager(IModuleInitializer moduleInitializer, 
                             IModuleCatalog moduleCatalog, 
                             ILoggerFacade loggerFacade) 
    : base(moduleInitializer, moduleCatalog, loggerFacade)
  {
  }

  // Replace the module loader with our own
  public override IEnumerable<IModuleTypeLoader> ModuleTypeLoaders
  {
    get
    {
      if (this.typeLoaders == null)
      {
        this.typeLoaders = new List<IModuleTypeLoader>()
                           {
                             new CustomXapModuleTypeLoader()
                           };
      }

      return this.typeLoaders;
    }

    set
    {
      this.typeLoaders = value;
    }
  }
}

This module manager is mostly used so I can get at the module loader list.  In this case I just returned a list containing my own custom XapModuleTypeLoader as shown above.  My custom module loader looks like this:

public class CustomXapModuleTypeLoader : XapModuleTypeLoader
{
  protected override IFileDownloader CreateDownloader()
  {
    return new CustomFileLoader();
  }
}

 The thin implementation of the ModuleTypeLoader is to simply inherit from the existing XapModuleTypeLoader class and just override the CreateDownloader to return a custom downloader. The custom downloader is key as that is what downloads and returns the Stream that contains the actual .xap file. By writing my own, I can intercept the .xap file before it gets returned.  Here is the CustomFileLoader:

public class CustomFileDownloader : IFileDownloader
{
  FileDownloader dler = new FileDownloader();

  public CustomFileDownloader()
  {
    dler.DownloadCompleted += 
      new EventHandler<DownloadCompletedEventArgs>(dler_DownloadCompleted);
  }

  void dler_DownloadCompleted(object sender, DownloadCompletedEventArgs e)
  {
    // Remove the event handler (so we don't leak)
    dler.DownloadCompleted -= dler_DownloadCompleted;

    // If someone cares, decrypt the stream and throw the event
    if (DownloadCompleted != null)
    {
      if (e.Cancelled || e.Error != null)
      {
        DownloadCompleted(this, e);
      }
      else
      {
        // Before you return the resulting stream,
       // make any changes you need
        DownloadCompleted(this, 
          new DownloadCompletedEventArgs(e.Result, 
            e.Error, 
            e.Cancelled, 
            e.UserState));
      }

    }
  }

  #region IFileDownloader Members

  public void DownloadAsync(Uri uri, object userToken)
  {
    dler.DownloadAsync(uri, userToken);
  }

  public event EventHandler<DownloadCompletedEventArgs> DownloadCompleted;

  #endregion
}

The downloader is pretty simple in that it uses a FileDownloader to do the downloading and just provides a place where we can intercept the download before it returns stream.

All this code was essential written to allow us to replace the default implementation of the IModuleManager. But how do we use the new IModuleManager? Since Prism uses Unity for Dependency Injection, I realized I could just register my type with the container and it would be used:

public class Bootstrapper : UnityBootstrapper
{
  // ...

  protected override void ConfigureContainer()
  {
    Container.RegisterType<IModuleManager, CustomModuleManager>();
    base.ConfigureContainer();
  }
}

By simply registering the IModuleManager with the CustomModuleManager, Prism gets injected with my implementation of the interface.  Elegant.

This holds true for many parts of Prism. If you need to replace some implementation of the Prism framework, before you start modifying the source code, make sure you can't just implement the interface and use the container to inject it into the system.

You can get the source at:

http://wildermuth.com/downloads/CustomModularity.zip

 

Yes, I Am Still Talking About Prism - On The Connected Show!

The Connected Show

I had a chance to sit down (metaphorically) with Dmitry Lyalin  and Peter Laudati and talk about Silvelright, MVVM and Prism 2.0. Let me know if you agree, disagree or think that I am a little obsessed with IoC containers.

The Connected Show is a podcast on New Microsoft Technology for the developer community, produced independently by Dmitry Lyalin and Peter Laudati.

My Sillveright-Prism Article is Live!

MSDN Magazine

The new MSDN Magazine is out and my article on creating composite Silverlight applications using Prism is finally available. If you're building large scale Silverlight applications and need to learn how to compose pieces of your application together, go read the article!

 

 

 

 

Blend and Visual Studio - Why Two Tools?

Silverlight Logo

I am here at DevTeach and having a great time. I got in a discussion with several of the speakers about the common complaint of some Silverlight/WPF folks that they want Blend to be in Visual Studio; or why Cider has always been disabled by most dev's.

I hear the complaint a lot that developers want the functionality of Blend hosted in Visual Studio.  While I understand the desire, I've never been bothered by the dual programs. In fact, I think its better. Blend needs to be separate because its primarily for a Designer/UX role that isn't comfortable with the breadth of Visual Studio.

We have plenty of other solutions that have two overlapping tools: I can insert an Excel spreadsheet in Word but when I need to do an if/then analysis I use excel.  A single Office App would be silly. Finally (I think the most compelling example) is SQL Server.  When I am in Visual Studio, I can open a database connection and run queries, create stored proces and more.  But if I want to manage users, create backup plans or other DBA-like tasks, I go to SQL Server Management Studio. I can do many of the same tasks in both, but developers never ask for Microsoft to remove SQL Server Management Studio and fold it all into Visual Studio.  Different roles mean different tools (roles != people btw). 

What do you think?