02 May 2009

Why you need Fiddler if you're publishing web sites

I'm publishing a new web site today (this is my new project that's using Silverlight, SQLite, LINQ via DbLinq and WCF). Well I tried to publish it on Monday but ran into a snag with the service I used to talk to the database. I thought it was a url problem, so I spent maybe an hour or two messing around with web.config and the service references in my Silverlight project. I've learned a couple of valuable lessons here.

Changing service references around can be a real hassle. There's two solutions to this. First, you can just have two references to the service in your Silverlight project, just changing the using statement at the top of your files to the one you want. However this might mean changing your code in more than one place, which will get old. Second, you can use a ServiceHostFactory (I read about this here):

public class MySiteHostFactory : ServiceHostFactory
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
// Specify the exact URL of your web service
Uri webServiceAddress = new Uri(ConfigurationManager.AppSettings["ServiceUri_MySite"]);
ServiceHost webServiceHost = new ServiceHost(serviceType, webServiceAddress);
return webServiceHost;

And then add a key/value pair to your web.config. I did try this approach and it worked, but still didn't get to the root of my problem.

Get your policies straight. When you're deployed you'll probably want to lock down who can access your service. But in the meantime, open that policy right up. You'll need two files, clientaccesspolicy.xml and crossdomain.xml.

<?xml version="1.0" encoding="utf-8"?>
<allow-from http-request-headers="*" >
<domain uri="*"/>
<resource path="/" include-subpaths="true"/>

And crossdomain.xml:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<allow-http-request-headers-from domain="*" headers="*"/>
NotFound can mean a lot of things. I kept getting a NotFound error out of my service. This was where I spent most of my time. Publishing the service? No prob. Opening up cross domain access? No prob. NotFound? What the heck does that mean. I could browse to the service. I could build a proxy using svcutil.exe. I was running my Silverlight app locally so I knew everything else was running right. So what the heck was going on? Well, a lot of messing around went by and still I didn't get anywhere until I did this:

Use Fiddler and add this to your web.config: <serviceDebug includeExceptionDetailInFaults="true" />. Using these two I found the issue in 10 minutes. Keep in mind that I was running the Silverlight app locally but I was pointing to the remote server. Turned out I was missing a dll (System.Data.SQLite). So I added it from my local dblinq directory. Still got the NotFound error. What?? Back to Fiddler. Go to the line that has the error (a 500 in my case) then Inspectors, TextView in the bottom pane. "The located assembly's manifest definition does not match the assembly reference": ah hah, wrong dll. Uploaded the correct one and away we went. All done.

Update: seetha asked what you need to do to get SQLite running on discountasp.net. The answer: not much. It's all about the trust level that your host let's you run .net apps under. Discountasp.net lets you run at Full Trust so there's no tweaking needed to get it going. Just make sure your app can find the .s3db file regardless of directory structure (I put mine in App_Data) and make sure you have the right version of your SQLite dll in your bin.