Friday, February 19, 2010

Silverlight 3, RIA and Fluent NHibernate

After working through some of the nice examples with Silverlight 4 and RIA Services I had to get back to the reality of the moment and look a RIA with SL3; this is something I had hoped not to do but it has been an interesting time.


I found a few bits and pieces on the web and some samples, none of which worked when opened in Visual Studio - all those version differences and breaking changes take their toll on such samples.


One such example was provided by Shane Kercheval at http://www.shanekercheval.com/?p=66.


Like the others however, this would not build for me and I spent some time getting things up to date for the latest version of RIA and working through those breaking changes; changes such as removing the HttpHandlers and replacing with HttpModules for the RIA Domain Services, using WebContext instead of RiaContext (one that caused me much wasted time when first looking at RIA samples and wondering why they would not work for me). 
A great help on this front was found here http://www.whycantyoucode.com/2009/11/verbose-steps-to-migrate-a-silverlight-application-from-net-ria-services-july-09-to-wcf-ria-services-pdc-09/


I also had to update a hardcoded database path (in NHibernateSessionFactory.cs, you will too if you want to run the code - unless by some fluke you have matching paths).  It is a sample after all so I can accept that (my plan is to use SQL Server for the PoC work).


Once I had eventually got things building the app would not run for me (note: I did not attempt to sort the Region / Country issue mentioned in the comments of Shane's post - I commented the validation code out as that was not pressing for me just now). 


Another waste of time?  Not this time - I was determined to get this one up and running as my primary goal for the evening was to have a working sample of SL3, RIA Services and Fluent NHibernate.  The code was building, just not running.


The services were returning 'Not Found' errors on the GetRegions and GetContacts methods.  Of course, right now RIA returns this error for any server side error, so I used Fiddler and found it was actually a 500 error coming back.


Checking the event log I found an error that gave me my exception:



System.NullReferenceException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Object reference not set to an instance of an object.

at System.Web.Ria.Services.DomainServiceVirtualPathProvider.OwnsFile(String virtualPath)
at System.Web.Ria.Services.DomainServiceVirtualPathProvider.FileExists(String virtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)

System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.Ria.Services.DomainServiceVirtualPathProvider.OwnsFile(String virtualPath)
at System.Web.Ria.Services.DomainServiceVirtualPathProvider.FileExists(String virtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)



This suggested that the virtual path provider was not finding my service, so next I tried something I should have done some time ago, I attempted to hit the services in a browser.  The service did not display as expected - you know the usualy screen you see for a WCF service.


A little more digging around and I decided to add .svc files for each service (and an associated Host Factory) so that I could prove to myself that the services were there are working.
These are quite simple a to add, just add a text file named -.svc replacing any "." with "-" (BusinessApp-Web-BusinessAppDomainService.svc in this case) and the file should contain code such as:


<%@ ServiceHost
Service="BusinessApp.Web.BussinessAppDomainService"
Factory="System.Web.Ria.BusinessAppDomainServiceHostFactoryEx"
%>




It worked! Now I finally have a sample working on my machine (I think I made it sound easier than it was here, but was too early in the morning to put all the woes down here).


Thanks to Shane and of course Brad A for thier part in putting things together.


Download the updated source here.


(Of course - you might not get it to build 1st time but most of the work has been done for you and it's always a good learning experience to hit and resolve problems!!  One thing that is very possible is that you will need to remove and re-add some references - I think this can be due to having 32bit vs 64bit OS on machines)

Using Fiddler with ASP.NET Web Development Server with Silverlight in IE

Whilst trying to debug an issue with Silveright RIA services I wanted to use Fiddler to see what was being returned by the server (as the client told me the service/method was not found - this is not the whole truth it turned out).


My first problem was that the ASP.NET Web Development Server (WDS) starts on a URL such as http://localhost:4567/default.aspx and when using IE on localhost Fiddler will not capture the traffic.

What you need to do is use a name other than localhost then Fiddler will capture for you. However, as WDS cannot be (from what I found) changed to start on anything but localhost Fiddler needs to know how to handle this.

What is needed is Rule in Fidder to handle this, a rule than will take the URL


http://mydomain:4567/default.aspx


and change it to


http://127.0.0.1:4567/default.aspx


This is pretty simple to setup. CTRL+R in Fidder will bring up the Fidder2 Script Editor in which you can edit your rules.
Find the function static function OnBeforeRequest(oSession: Session) and at the end of it add a rule like so:


oSession.host = oSession.host.replace("mydomain","127.0.0.1");


Save you updated rules script and exit.

Now, when you browse (/debug) your Silverlight app you should do so using http://mydomain:4567 rather than localhost and traffic will be captured.

One minor irritation that I also had to overcome was that when the SL project started (and immediately hit an error) it was doing so on http://localhost:4567/ and so I did not see the traffic.

To get around this problem I added a start page (actually just edited the default.aspx in the SL web project) so that it contains a hyperlink to the Silverlight test page using the required URL such as http://mydomain:4567/SLAppTestPage.aspx; this page now having traffic captured by Fiddler and allowing me to see the real reason behind my RIA Service call failures.

Wednesday, February 10, 2010

Silverlight RIA samples with SQL 2005

I have recently been looking at RIA with Silverlight 4 and Visual Studio 2010.

Brad Abrams has some great posts on all of this and also touched on a subject that I will be looking into a little more - RIA DomainService with NHibernate.

One thing I found is that the the examples use a modified Northwind database with the SuperEmployee table - this comes with the samples but it is a SQL 2008 database.  I needed to have this run off SQL 2005 as my target platform has 2005 and I wanted to be sure all is going to be OK when we put it out there (and one development machine does not yet have SQL 2008 installed on it).

As there is no 'downgrade' for the database to attach it is SQL 2005 I decided to find use an instance of SQL 2008, attached the MDF supplied with the code for one of Brads posts and then use the SQL Database Publishing Wizard (build into Visual Studio 2008) to script the database and target that script for SQL Server 2005.

To get the SQL Server 2005 database setup follow these steps:

1. Create a new empty database (I called mine SuperNorthwind)

2. Execute the SQL script found here against your new database


You will of course needs to tweak your connection strings accordingly but should be good to go with 2005 for the RIA samples now.

SQL Server 2008 installation problem - restart required.

Tried to install SQL Server Developer Edition on Windows 7 Ultimate.

There are 6 initial checks made before installation starts, one of which is "Restart Computer" - this is where I kept getting stuck. I could restart but still nothing doing.

A few posts suggested that the registry was to blame for my troubles, specifically the "PendingFileRenameOperations" value in "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager".

The value stored here was:

\??\C:\Windows\TEMP\logishrd\LVPrcInj03.dll

\??\C:\Windows\TEMP\logishrd\

\??\C:\Windows\TEMP\logishrd\LVPrcInj04.dll

\??\C:\Windows\TEMP\logishrd\

(These are apparently linked to Logitech and the webcam I have installed).

I cleared the values and restarted - same thing. Also, the values were back in the registry key.

So I decided I'd rename "PendingFileRenameOperations" and then tried the install again (without restarting). This did the trick and I was able to install SQL 2008 (then of course I renamed the key to the original name).