<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Shiny Objects</title><subtitle type="html" /><id>http://blogs.msdn.com/tom_laird-mcconnell/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tom_laird-mcconnell/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/tom_laird-mcconnell/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2009-03-25T21:21:00Z</updated><entry><title>Creating an ADO.NET Data service proxy as workaround for Silverlight/ADO.NET cross domain issue</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tom_laird-mcconnell/archive/2009/03/25/creating-an-ado-net-data-service-proxy-as-workaround-for-silverlight-ado-net-cross-domain-issue.aspx" /><id>http://blogs.msdn.com/tom_laird-mcconnell/archive/2009/03/25/creating-an-ado-net-data-service-proxy-as-workaround-for-silverlight-ado-net-cross-domain-issue.aspx</id><published>2009-03-25T23:21:00Z</published><updated>2009-03-25T23:21:00Z</updated><content type="html">&lt;P&gt;ADO.NET Data Service provides a fantastic service for consuming data from SilverLight.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Unfortunately, there is a fly in the ointment when it comes to consuming data across multiple domains.&amp;nbsp; The problem is that the the implementation of ADO.NET Data Services (Astoria) doesn’t work cross domain from SilverLight, even if there is a clientaccesspolicy.xml file.&amp;nbsp; Apparently the network stack that it uses is not the normal Silverlight one.(See Pablo Castro’s blog for details)&lt;/P&gt;
&lt;P&gt;This is a bummer, as now instead of having a great rich client object model around your database you are back in the business of having to create a proxy service implementation.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;This blog post shows a very easy way to work around this problem by create a proxy service which is fully functional object model with very little code.&lt;/P&gt;
&lt;P&gt;Let’s start with an hypothetical project:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://foo.com/FooStore.svc" mce_href="http://foo.com/FooStore.svc"&gt;http://foo.com/FooStore.svc&lt;/A&gt;&amp;nbsp; is Astoria service called &lt;STRONG&gt;FooStore&lt;/STRONG&gt;.&lt;STRONG&gt;svc &lt;/STRONG&gt;around a LINQ database.&amp;nbsp; 
&lt;LI&gt;&lt;A href="http://myapp.com/" mce_href="http://myapp.com"&gt;http://myapp.com&lt;/A&gt; has a web service with a silverlight application in it where you want to consume FooStore.svc from.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;U&gt;Step 1- Add Service Reference to the Database Web Service&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;Add a service reference for &lt;A href="http://foo.com/FooStore.svc" mce_href="http://foo.com/FooStore.svc"&gt;http://foo.com/FooStore.svc&lt;/A&gt; to your web service &lt;A href="http://myapp.com/" mce_href="http://myapp.com"&gt;http://myapp.com&lt;/A&gt;.&amp;nbsp; Visual Studio will create a DataServiceContext class around that service and the entities it provides.&lt;/P&gt;
&lt;P&gt;This gives your application a full blown LINQ based web service with the ability to consume and interact with the database on foo.com. Cool!&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Step 2 – Create new proxy service on the Application Web Service&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;Create a new ADO.NET Data Service on &lt;A href="http://myapp.com/" mce_href="http://myapp.com"&gt;http://myapp.com&lt;/A&gt; called &lt;STRONG&gt;FooStoreProxy.svc.&lt;/STRONG&gt; This will be the service that your silverlight application will consume, which you want to look exactly like FooStore.svc but be on your domain. &lt;/P&gt;
&lt;P&gt;&lt;U&gt;Step 3 – Wrap database service and override CreateDataSource()&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;Now you need to simply use the Astoria model which was generated in step 1 as the entity model that the new proxy service is wrapped around.&amp;nbsp; It will take anything that returns IQueryable as objects in the new service, and we have a brand new shiny one which we created in step 1. &lt;/P&gt;
&lt;P&gt;You will probably need to override the CreateDataSource() method so you can pass your connection string to the ADO.NET Data Service you are consuming like this:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; FooStoreProxy : DataService&amp;lt; FooStore&amp;gt;
{
    &lt;SPAN class=rem&gt;// This method is called only once to initialize service-wide policies.&lt;/SPAN&gt;
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; InitializeService(IDataServiceConfiguration config)
    {
        &lt;SPAN class=rem&gt;// TODO: set rules to indicate which entity sets and service operations are &lt;BR&gt;        // visible, updatable, etc.&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// Examples:&lt;/SPAN&gt;
    } 

    &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; FooStore &lt;STRONG&gt;CreateDataSource&lt;/STRONG&gt;()
    {
        ConnectionStringsSection connectionStringsSection = &lt;BR&gt;               WebConfigurationManager.GetSection(&lt;SPAN class=str&gt;"connectionStrings"&lt;/SPAN&gt;) &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; ConnectionStringsSection;
        &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; connectionName = &lt;SPAN class=str&gt;"default"&lt;/SPAN&gt;; 
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; FooStore(connectionStringsSection.ConnectionStrings[connectionName].ConnectionString);
    } 
} 
&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;&lt;U&gt;Step 4 – Add Service Reference to FooStoreProxy.svc in your Silverlight Application&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;Configure your silverlight app by adding a service reference to &lt;A href="http://myapp.com/FooStoreProxy.svc" mce_href="http://myapp.com/FooStoreProxy.svc"&gt;http://myapp.com/FooStoreProxy.svc&lt;/A&gt; This will auto-generate a client wrapper around the proxy service.&lt;/P&gt;
&lt;P&gt;You now should be able to use the object model generated in your silverlight application to query the &lt;A href="http://myapp.com/FooStoreProxy.svc" mce_href="http://myapp.com/FooStoreProxy.svc"&gt;http://myapp.com/FooStoreProxy.svc&lt;/A&gt; service, which will then query the real &lt;A href="http://foo.com/FooStore.svc" mce_href="http://foo.com/FooStore.svc"&gt;http://foo.com/FooStore.svc&lt;/A&gt; service.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;If all you want to do is to have read only access you are done.&amp;nbsp; But if you want to be able to do CRUD operations then you have a couple more things will need to do.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Step 5 – implement &lt;STRONG&gt;IUpdateable &lt;/STRONG&gt;on the application web service&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;The reason you can’t update your service is because the class doesn’t implement &lt;STRONG&gt;IUpdateable&lt;/STRONG&gt;.&amp;nbsp; Luckily the generated class is a partial class, so you can just create a partial class file which adds the needed interface.&lt;/P&gt;
&lt;P&gt;Here’s code which shows a complete implementation of IUpdateable which should be generic and work in most cases:&lt;/P&gt;&lt;PRE class=csharpcode&gt; &lt;SPAN class=rem&gt;// Add IUpdateable to our ADO.NET Data Services generated DataServiceContext wrapper&lt;/SPAN&gt;
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;partial&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; FooStoreProxy : IUpdatable
    {
        &lt;SPAN class=preproc&gt;#region&lt;/SPAN&gt; IUpdatable Members
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; AddReferenceToCollection(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource, &lt;BR&gt;                                             &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; propertyName, &lt;BR&gt;                                             &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; resourceToBeAdded)
        {
            &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.AddLink(targetResource, propertyName, resourceToBeAdded);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ClearChanges()
        {
            &lt;SPAN class=rem&gt;// clear out links&lt;/SPAN&gt;
            &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (var link &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.Links)
                &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.DetachLink(link.Source, link.SourceProperty, link.Target);
            
            &lt;SPAN class=rem&gt;// clear out entities&lt;/SPAN&gt;
            &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (var entity &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.Entities)
                &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.Detach(entity.Entity);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; CreateResource(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; containerName, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; fullTypeName)
        {
            &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; obj = Activator.CreateInstance(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;.GetType().Assembly.GetType(fullTypeName));
            AddObject(containerName, obj);
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; obj;
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; DeleteResource(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource)
        {
            DeleteObject(targetResource);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; GetResource(IQueryable query, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; fullTypeName)
        {
            &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; resource = query.Cast&amp;lt;&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt;&amp;gt;().SingleOrDefault();

            &lt;SPAN class=rem&gt;// fullTypeName can be null for deletes&lt;/SPAN&gt;
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (fullTypeName != &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; &amp;amp;&amp;amp; resource.GetType().FullName != fullTypeName)
                &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Exception(&lt;SPAN class=str&gt;"Unexpected type for resource"&lt;/SPAN&gt;);
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; resource;
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; GetValue(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; propertyName)
        {
            Type type = targetResource.GetType();
            PropertyInfo propInfo = type.GetProperty(propertyName);
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (propInfo == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)
                &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Exception(&lt;SPAN class=str&gt;"Can't find property"&lt;/SPAN&gt;);
            &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; val = propInfo.GetValue(targetResource, &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;);
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; val;
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; RemoveReferenceFromCollection(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource, &lt;BR&gt;                                                  &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; propertyName, &lt;BR&gt;                                                  &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; resourceToBeRemoved)
        {
            &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.DeleteLink(targetResource, propertyName, resourceToBeRemoved);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; ResetResource(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; resource)
        {
            Detach(resource);
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; resource;
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; ResolveResource(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; resource)
        {
            &lt;SPAN class=rem&gt;// just reflect the object back, since that's what we &lt;BR&gt;            // gave them in CreateResource&lt;/SPAN&gt;
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; resource;
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; SaveChanges()
        {
            &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.SaveChanges();
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; SetReference(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; propertyName, &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; propertyValue)
        {
            &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.SetLink(targetResource, propertyName, propertyValue);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; SetValue(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; targetResource, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; propertyName, &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; propertyValue)
        {
            PropertyInfo propInfo = targetResource.GetType().GetProperty(propertyName);
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (propInfo == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)
                &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Exception(&lt;SPAN class=str&gt;"Can't find property"&lt;/SPAN&gt;);
            propInfo.SetValue(targetResource, propertyValue, &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;);
        }

        &lt;SPAN class=preproc&gt;#endregion&lt;/SPAN&gt;
    }
}&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;You should now be able to do CRUD operations against your store!&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;U&gt;Step 5 – Add &lt;STRONG&gt;IExpandProvider&lt;/STRONG&gt; implementation to the application web service&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;There is one thing left which does not work quite yet.&amp;nbsp; ADO.NET Data Services has a special LINQ command called Expand().&amp;nbsp; This lets you control the shape of the results which come back to reduce roundtrips.&amp;nbsp; To make the proxy handle Expand correctly you need to implement IExpandProvider interface on FooStoreProxy.&amp;nbsp; Luckily, while the documentation is thin the implementation is quite straight forward.&lt;/P&gt;
&lt;P&gt;Here is an implementation which you will need to replace only the switch block with each entity that is exposed by your service:&lt;/P&gt;&lt;PRE class=csharpcode&gt;        &lt;SPAN class=rem&gt;/// &lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;/// IExpandProvider &lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;/// implements the $expand syntax by simply passing through to the proxied ADO.NET Data Service&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;/// &lt;/SPAN&gt;
        &lt;SPAN class=preproc&gt;#region&lt;/SPAN&gt; IExpandProvider Members
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; IEnumerable ApplyExpansions(IQueryable queryable, ICollection expandPaths)
        {
            &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; expand = &lt;SPAN class=str&gt;""&lt;/SPAN&gt;;
            &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (var expandSegmentCollection &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; expandPaths)
            {
                &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; segment = &lt;SPAN class=str&gt;""&lt;/SPAN&gt;;
                &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (var expandSegment &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; expandSegmentCollection)
                {
                    segment += String.Format(&lt;SPAN class=str&gt;"{0}{1}"&lt;/SPAN&gt;, (segment.Length &amp;gt; 0) ? &lt;SPAN class=str&gt;"/"&lt;/SPAN&gt; : &lt;SPAN class=str&gt;""&lt;/SPAN&gt;, expandSegment.Name);
                }
                &lt;FONT color=#000000&gt;&lt;SPAN class=rem&gt;// whatever entity type this query is using needs to to use a &lt;/SPAN&gt;
                &lt;SPAN class=rem&gt;// strongly typed DataServiceQuery object to get access to the AddQueryOption...bummer&lt;/SPAN&gt;
                &lt;SPAN class=kwrd&gt;switch&lt;/SPAN&gt; (queryable.ElementType.Name)
                {
                    &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; &lt;SPAN class=str&gt;"Item"&lt;/SPAN&gt;:
                        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; ((DataServiceQuery&amp;lt;Item&amp;gt;)queryable).Expand(segment);
                    &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; &lt;SPAN class=str&gt;"Person"&lt;/SPAN&gt;:
                        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; ((DataServiceQuery&amp;lt;Person&amp;gt;)queryable).Expand(segment);&lt;BR&gt;                      &lt;/FONT&gt;&lt;FONT color=#000000&gt;&lt;SPAN class=rem&gt;// add/remove entries here for each item type that is queried as a result set.                &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN class=rem&gt;                      // NOTE: The switch statement and DataServiceQuery&amp;lt;ElementType.Name&amp;gt; must match&lt;/SPAN&gt;
                }
            }            &lt;BR&gt;&lt;/FONT&gt;&lt;SPAN class=rem&gt;            // return massaged query&lt;BR&gt;&lt;/SPAN&gt;            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; queryable;
        }
        &lt;SPAN class=preproc&gt;#endregion&lt;/SPAN&gt;
&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;And there you go.&amp;nbsp; This is relatively easy to use and seems to work just great.&amp;nbsp; I would love to hear from others if this works for them too!&lt;/P&gt;
&lt;P&gt;-Tom&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9509558" width="1" height="1"&gt;</content><author><name>Tom Laird-McConnell</name><uri>http://blogs.msdn.com/members/Tom+Laird-McConnell.aspx</uri></author><category term="Astoria" scheme="http://blogs.msdn.com/tom_laird-mcconnell/archive/tags/Astoria/default.aspx" /><category term="Silverlight" scheme="http://blogs.msdn.com/tom_laird-mcconnell/archive/tags/Silverlight/default.aspx" /><category term="ADO.NET Data Services" scheme="http://blogs.msdn.com/tom_laird-mcconnell/archive/tags/ADO.NET+Data+Services/default.aspx" /></entry></feed>