That is a great post - thank you!
We'll look into ways you can do this without modifying existing CSLA code.
It may be possible now - I haven't gone through it. But the primary extensibility mode for the data portal is for you to create your own WcfProxy and WcfHost classes that encapsulate any custom behavior. Like the pure-.NET data portal, you can entirely replace the communication channel used by the data portal.
But we'll look through that to make sure it is possible to achieve this scenario in some manner along that line.
I'm not real interested in taking a dependency on an external library into core CSLA (already have one - don't like it, but can't really avoid it), but I do want to make it practical as an add-on to CSLA.
But can't you just use http 1.1 compression? This was my expectation - that people would just enable http compression through IIS and be done with it?
I don’t have any examples of replacing the proxy/host in
Silverlight. It is not terribly hard though, because everything is
interface-based.
You can, for example, copy the WcfProxy and WcfHost classes into
your own projects (SL and .NET respectively) and configure the client to use
your proxy class, and the server’s WCF endpoint to your use host class
and you are set.
Rocky
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Monday, September 22, 2008 9:23 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] CSLA Light - Adding JIT object compression to
WCF calls
Hi Rocky
I agree that putting a SharpZipLib dependency into CSLA is a bad idea.
I'll definitely have a look into extending the WcfProxy in order to build my
compress/decompress functionality on top of CSLA rather than into it. Do
you have any examples of how I should go about this?
Regarding the HTTP 1.1 compression, that was also my first idea but searching
the web for some examples of how to implement this with WCF seemed to indicate
that WCF does not in fact support HTTP 1.1. compression out the box.
This MSDN
forum post in particular turned me off the idea of trying to use IIS to
compress the responses. Additionally, the HTTP 1.1 compression is based
on GZip, which Silverlight does not have - so I didn't want to go through
trying to get that working only to hit issues when trying to
decompress/compress in the SL client.
If I've missed something with the HTTP 1.1 compression I'm all ears :)
Csla version 3.6 has been extended to provide more generalized implementation of the requested compression functionality. Silverlight WCF Proxy and corresponding host classes have been expanded to contain virtual methods to convert request and response objects prior to sending them across the wire. As a result, you can create two custom classes (one inherits from WcfProxy<T>, the other one from Csla.Server.Hosts.Silverlight.WcfPortal) and provide additional functionality. This implementation is not only allowing you to create a compressed proxy, but also opens the door for other potential issues, such as encryption. There is a sample project under “samples\trunk\CslaLight\cs(and vb)\” The project is called RemotePortalWithCompressedProxy. It is using ICSharpZipLib to create a compressed proxy. Please feel free to take a look. Please note that .ClientCOnfig file has been updated as well as web.config and .svc file to refer to new proxy and server. Also, Silverlight app upon startup sets up new proxy type.
Thanks for the suggestion and let us know if you have any questions.
Sergey.
Great to hear that. I will fix the sample project once I
have a second.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: paupdb
[mailto:cslanet@lhotka.net]
Sent: Monday, September 29, 2008 8:15 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: CSLA Light - Adding JIT object compression
to WCF calls
I've implemented the compression functionality as per your
sample project and was able to get up and running with it very quickly.
Thanks Sergey, this is a very easy and clean solution.
One little bug in the Sample project - if you submit a request with no Criteria
specified (i.e. request.CriteriaData is null), then the code bombs trying to
compress a null object.
FYI, I'm going to probably implement this functionality only on the ObjectData
and only when the ObjectData is over a certain size.
So I'll leave the Criteria, Global and UserContext components uncompressed to
try to save unnecessary compress/decompress overhead.
The great thing about your implementation is that I am able to have this level
of control :)
What an awesome thread! An excellent post requesting increased functionality in Csla and showing one way to do it. Compression is something that could be very useful to many developers and we won't all know how to implement it. Then a change to the framework allowing it to be implemented in a flexible fashion just a couple of days later!
Great job and thanks to all involved.
Joe
Thanks James, that's great! I added it to the FAQ too
http://www.lhotka.net/cslanet/faq/SilverlightDataPortalCompression.ashx
You guys rock! I just used these instructions and in less that 20 minutes took an xml reponse of over 2560 kb down to 88kb.
Thanks for the great posts,
Dustin
OK I followed those steps exactly and have my project set up just like InventoryDemo. But when I run I get this error with the very first DP call:
"The remote server returned an error: NotFound"
I set a break point in the CompressedProxy.ConvertRequest function and it gets there OK. But it never gets any further from what I can tell.
Does anyone have any ideas as to what I may be doing wrong?
It is almost always a configuration issue. Client config, server config and svc file - they all need to agree.
I checked that. Here they are in case I missed something obvious:
Web.Config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WcfPortalBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IWcfPortal" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="10000000" maxReceivedMessageSize="10000000">
<readerQuotas maxStringContentLength="10000000" maxArrayLength="10000000" maxBytesPerRead="10000000" />
<!--<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>-->
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WcfPortalBehavior" name="Profiler.Core.Compression.CompressedHost">
<endpoint address="" binding="basicHttpBinding" contract="Csla.Server.Hosts.Silverlight.IWcfPortal" bindingConfiguration="BasicHttpBinding_IWcfPortal">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</service>
</services>
</system.serviceModel>
WcfPortal.svc:
<% @ServiceHost Service="Profiler.Core.Compression.CompressedHost" %>
ServiceReferences.ClientConfig:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IWcfPortal" maxBufferSize="10000000"
maxReceivedMessageSize="10000000" receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:2374/WcfPortal.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IWcfPortal"
contract="WcfPortal.IWcfPortal" name="BasicHttpBinding_IWcfPortal" />
</client>
</system.serviceModel>
Hi,
regarding the section:
Web service project:
1. Find <service... section in
<system.serviceModel> and change the name to
'YourBusinessLibrary.Compression.CompressedHost'.
2. Do the same in
WcfPortal.svc.
I currently have:
<services>
<service behaviorConfiguration="HeavonyLight.Web.HeavonyServiceBehavior" name="HeavonyLight.Web.HeavonyService">
<endpoint address="" binding="customBinding" bindingConfiguration="HeavonyLight.Web.HeavonyService.customBinding0" contract="HeavonyLight.Web.HeavonyService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
I use Silverlight 4.0 and have downloaded the relevant 4.0 samples from the project page. I am 10/10 up till this step. Now I'm stuck.
Any clues on a likely configuration with this CustomBinding stuff in place?
Cheers.
EDIT:
I went into the test application and ripped out the plumbing from there.
I'll let you know how my experience goes, Im guessing I need to read up on how channels work some more :)
Thanks.
Hi all,
I loved the solution, specially how fast everything can be up and running. I admit I didn't know InventoryDemo uses compression. One point remains to be solved (and not a minor one): the license model.
The Silverlight version of SharpZipLib referenced is SharpZipLib.dll dated Aug 5 2008 and mentions a copyright by HP(???). There are later versions for Silverlight3, Silverlight4 and WindowsPhone7 dated Aug 14 2010.
Both SharpZipLib (the .NET version) and SharpZipLib.Silverlight are GPL licensed but both have an exception.
The former states the exception clearly on their home page http://www.icsharpcode.net/opensource/sharpziplib/
The later uses Codeplex that provides limited licensing functionality. So the same exception can be read on a "Discussions" message http://slsharpziplib.codeplex.com/Thread/View.aspx?ThreadId=85286
The exception is the same on both products and states:
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version
So this is kind'a chameleon license. If we distribute/sell a product under CSLA license, we can include this library under the same umbrella and we aren't obliged to open source the applications that use these libraries.
Keep in mind that CSLA has absolutely no dependency on SharpZipLib - we just use it for samples because it is free. If you have issues with that component or its license, there are other (commercial) compression libraries available, and you should be able to use them in place of SharpZipLib in your code with no problem.
I'm not sure how its licensing compares but have a look at DotNetZip library
We were a bit frustrated with SharpZipLib (assembly size for download to the Silverlight client, and incompatibility with .NET compression, and a few others). After some looking around found DotNetZip library - we adapted the ZLib component and created a .NET and a Silverlight version. We plugged this into CSLA and ripped out SharpZipLib. (Ps: the ZLib component is the core ZLib compression engine only, without extra other fluff like files/archives/etc.)
The did some extensive testing which showed a twofold improvement that not only reduced the Silverlight DLL size from 139Kb to 79Kb, but it also give a smaller and faster compression speed than SharpZipLib did - (about 3-8% in our experience with CSLA Binary business objects). Been using it since.
I've been trying to work with the project owner to get the Silverlight version to be part of his release library, and offered to do the work. We are not there yet but he agreed to it. Since then I have added the Silverlight project to the solution and checked it in, but unfortunately he doesn't have the VS2010 or the Silverlight tools for VS2008 and not very quick to make changes to the release DLL's. Also, he keeps the key file for signing the project out of the public source (understandably so). The bottom line is you cannot download a signed Silverlight ZLib DLL from the codeplex project yet, but you can easily build your own (using your own key file).
Alternatively, I can send you his .NET and my adapted Silverlight ZLib assembly (signed with a randomly generated key file), just let me know.
Edit: Here's the link to the DotNetZip site: http://dotnetzip.codeplex.com/
Hi Janns,
Under the scope of Remoting I've done a lot of testing of compression libraries:
SharpZipLib resulted in the best compression but it was so slow that the complete transmission time (start of compression - transmission - end of decompression) wasn't good at all. Of course this also depends on the transmission bandwidth; the slower the media, the more important the compression ratio is.
The .NET library itself was rule out as a single test was enough to prove it suffers from a very well known problem at least since MNP5/v.42bis modems (MNP5 compression processes ZIP files but the resulting file is larger than the original; V.42bis solved that problem). But this "inflate on compression" problem was fixed in .NET 4.0
http://msdn.microsoft.com/en-us/library/ms171868(v=VS.100).aspx
"The compression algorithms for the System.IO.Compression.DeflateStream and System.IO.Compression.GZipStream classes have improved so that data that is already compressed is no longer inflated."
So this is now a serious alternative to SharpZipLib.
In the mean time, your solution is the one that is working.
Copyright (c) Marimer LLC