Thursday, December 30, 2010

WCF and ECO

I have been debugging the Remote persistence we use for ECO6 – this uses WCF. It was Jonas that started this work and he did a fine job – but we have a few gotchas that I want to get documented here.

If you build your own server (Remote persistence server for ECO), either as WindowsService or as a WinForm application (both available from the ECO VS Wizard) we use the WCF class ServiceHost.

In this ServiceHost we set some parameters – like what binding to use and so on. During the beta-phase of ECO6 it became apparent that we also needed to set a lot of other values like MaxReceivedMessageSize and MaxBufferPoolSize etc on the Binding object.

That code came to look like this:

BasicHttpBinding binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = maxReceivedMessageSize;
binding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
binding.MaxBufferSize = int.MaxValue;
binding.MaxBufferPoolSize = 0; 
Uri address = new Uri(uri);
ServiceHost svc = new ServiceHost(t, address);
svc.AddServiceEndpoint(typeof(IPersistenceMapperWCF), binding, address);

The gotcha with this is that if you host your Remote persistence server in IIS – we do NOT use the ServiceHost because then IIS IS provides the ServiceHost for us.

So in this case we need to tune up the MaxReceivedMessageSize and MaxBufferPoolSize etc some other way : web.config.

So in your IIS hosted Remote Persistent Server you need to add something like this to your web.config:

<system.serviceModel>
  <services>
    <service name="Frako.Emvis.PServerWebService.EmvisPMPWCF" behaviorConfiguration="TheBehavior">
 
      <endpoint address=""
                binding="basicHttpBinding"
                bindingConfiguration="TheBindingConfiguration"
                contract="Eco.Wcf.Common.IPersistenceMapperWCF"  />  
 
    </service>
  </services>
  
  
  <bindings>      
    <basicHttpBinding>
      <binding name="TheBindingConfiguration"              
             maxReceivedMessageSize="104857600">
        <readerQuotas maxStringContentLength="104857600"/>
      </binding>
    </basicHttpBinding>
  </bindings>
  
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      <behaviors>
          <serviceBehaviors>
              <behavior name="TheBehavior">
          
        <serviceDebug includeExceptionDetailInFaults="true" />
        <dataContractSerializer maxItemsInObjectGraph="2147483646" />
 
 
      </behavior>
          </serviceBehaviors>
      </behaviors>
  </system.serviceModel>

Here is the same thing as an image with some hints:

The green line is the name of your service – this is the name of your subclass of the PersistenceMapperProvider.

The blue lines shows where we adjust some values to allow for bigger messages

The red lines just explains how reference and definition is separated

image

Having your own (enum) types

Another thing that got us stumped for a good 30 seconds was the unexpected server shutdown when trying to transfer types used by modlr-attributes over WCF when these types were not known to the service.

This is common place when you do your own Enumerations for example or any other handy attribute-type you might want to use.

You need to tell the WCF service about these types before the service is started. And you need to tell the client AND the server.

In a IIS hosted server use the Global.asax:

protected void Application_Start(object sender, EventArgs e)
{
    Eco.Wcf.Common.KnownTypesHelper.AdditionalTypes.Add(typeof(OrgeinheitTypEnum));
    Eco.Wcf.Common.KnownTypesHelper.AdditionalTypes.Add(typeof(ECObjectTypEnum));
}

And on the Client add it to Main:

static void Main()
{
    Eco.Wcf.Common.KnownTypesHelper.AdditionalTypes.Add(typeof(OrgeinheitTypEnum));
    Eco.Wcf.Common.KnownTypesHelper.AdditionalTypes.Add(typeof(ECObjectTypEnum));
    

When things do not work – complete darkness

Debugging the WCF issues was initially really annoying and complex – “Unexpected server shutdown” and nothing else…

But luckily it easy to turn on explicit logging in WCF. Go like this in the server web.config:

<configuration>
 
<system.diagnostics>
  <sources>
    <source name="System.ServiceModel"
            switchValue="Information, ActivityTracing"
            propagateActivity="true">
      <listeners>
        <add name="traceListener"
            type="System.Diagnostics.XmlWriterTraceListener"
            initializeData= "c:\temp\WCFTracelog.log" />
      </listeners>
    </source>
  </sources>
</system.diagnostics>
 
</configuration>

This will give you a file with a lot of information at c:\temp\WCFTracelog.log.

Like when I had removed one of the AdditionalTypes.Add statements from above the log look like this:

image

7 Comments:

Anonymous Anonymous said...

Very nice. Now I see the configuration is as in a classical WCF-Service with IIS-Hosting, everything is explicitelly declared.
The Service Contract is explicitelly referenced in endpoint definition ("Eco.Wcf.Common.IPersistenveService").
Does it give us developers the possibility to extend it with our own OperationContracts, e.g. by subclassing the interface and implementing new methods in the derivate of PersistenceMapperProvider?
If not what approach would be the best to write own WCF Services under ECO?

December 30, 2010 at 9:09 PM  
Blogger Hans Karlsen said...

If you want to communicate with your server for other reasons than for Persistance mapping the most logical solution is to define another service. This new service implements another contract that you define yourself.

Your server can expose multiple services so there is not need to trying to extend this one.

December 31, 2010 at 11:15 AM  
Anonymous william said...

This is the basicHttpBinding I used for IIS hosted Eco Wcf server:





I think I need to specify transferMode for BLOB field to work properly?

January 3, 2011 at 8:35 AM  
Anonymous Anonymous said...

guest00:
Hi Hans
How to use another Binding?
I see only basicHttpBinding...
Thank you

January 12, 2011 at 6:18 PM  
Blogger Hans Karlsen said...

I added a new post detailing usage of other bindings. This new post requires new ECO build.
http://theblog.capableobjects.com/2011/01/using-different-wcf-bindings-with.html

January 16, 2011 at 6:12 PM  
Blogger Rich said...

Thanks for this Hans. I forgot to re-Add my connection string after copying a new persistence server app generated from the templates into my project.
That yeilds total darkness! One thing you could do is be clear whether you are talking about app.config, web.config or both in the configuration details.

February 19, 2011 at 1:00 AM  
Anonymous Anonymous said...

I found SvcTraceViewer.exe useful when it comes to trace logs. Service Trace Viewer Tool (SvcTraceViewer.exe)documentation is here http://msdn.microsoft.com/en-us/library/ms732023.aspx

Another interesting tool is Configuration Editor Tool (SvcConfigEditor.exe) http://msdn.microsoft.com/en-us/library/ms732009.aspx
Pawel

February 24, 2011 at 1:56 PM  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home

 
Contact Us | Terms of Use | Privacy Statement © 2009 CapableObjects