C# is one of the most popular languages today and there are many reasons for this. It has many qualities that make it suitable for development for users at most all levels. Let’s discuss how efficiently transfer a large data from Client to WCF and Vice Versa Using .Net C#.
Windows Communication Foundation (WCF) is a framework for building service-oriented applications. Using WCF, we can send data as asynchronous messages from one service endpoint to another. A service endpoint can be part of a continuously available service hosted by IIS, or it can be a service hosted in an application.
Plan your Data usage between WCF and Client before you start your project. Then use the appropriate MessageEncoding and transferMode in your WCF web.config
Let us see the default web.config in WCF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?xml version="1.0"?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5"/> </system.web> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <!-- To avoid disclosing metadata information, set the values below to false before deployment --> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpBinding" scheme="http" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <directoryBrowse enabled="true"/> </system.webServer> </configuration> |
and the default App.config in a Client Application
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" /> </basicHttpBinding> </bindings> <client> <endpoint address=" http://localhost:8099/Service1.svc/processData" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract=" SuperService.IService1" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel> </configuration> |
The default MessageEncoding is “normal text XML” and the transferMode is “Buffered” – Buffered transfers hold the entire message in a memory buffer until the transfer is complete.
1 2 3 4 5 6 7 8 9 10 11 |
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="PowerTransmissionBinding" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647> <readerQuotas maxDepth="32" maxBytesPerRead="200000000" maxArrayLength="200000000" maxStringContentLength="200000000" /> </binding> </basicHttpBinding> </bindings> </system.serviceModel> |
In the above configuration the MessageEncoding and transferMode is not defined, but the system by default taken it as
1 2 |
<binding name="PowerTransmissionBinding" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Buffered" messageEncoding="Text"> |
The above configuration does not transfer the file with the size ≈>18 MB from and to the WCF. During the analysis the maxReceivedMessageSize=”2147483647″ all are seems good. But the default MessageEncoding is “normal text XML” and the transferMode is “Buffered” – Buffered transfers hold the entire message in a memory buffer until the transfer is complete. So, it does not support for the Large Bytes in terms of memory and transport. The Communication may get terminate depends upon the Network Traffic or any other circumstances. Due to this reason the application may get crashed.
So, we need to change the MessageEncoding to “MTOM” (Message Transmission Optimization Mechanism). (MTOM) is an efficient technology for transmitting binary data in Windows Communication Foundation (WCF) messages. The MTOM encoder attempts to strike a balance between efficiency and interoperability. The MTOM encoding transmits most XML in textual form, but optimizes large blocks of binary data by transmitting them as-is, without conversion to text.
Additionally we have to change the transferMode to “StreamedRequest” or “Streamed”. StreamedRequest gives better proformance then Streamed. The request message is streamed and the response message is buffered in StreamedRequest.
Let us consider the modified version of the web.config, it will support the large data transfer. Binding information should be inside the system.ServiceModel of Web.config in WCF Service
1 2 3 4 5 6 7 8 9 10 11 |
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="PowerTransmissionBinding" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="StreamedRequest" messageEncoding="Mtom"> <readerQuotas maxDepth="32" maxBytesPerRead="200000000" maxArrayLength="200000000" maxStringContentLength="200000000" /> </binding> </basicHttpBinding> </bindings> </system.serviceModel> |
and the EndPoint should be
1 2 3 4 5 6 7 8 |
<services> <service name="DataTestingWCF.Service1"> <endpoint address="processData" binding="basicHttpBinding" bindingConfiguration="PowerTransmissionBinding" contract="DataTestingWCF.IService1" /> </service> </services> |
readerQuotas :
It is WCF level setting, especially SOAP message and not about overall length of request. It puts various restrictions on the size of SOAP messages which can be processed by WCF endpoint. Those settings basically needed to prevent various kinds of a denial-of-service (DoS) attack against the service using xml messages prepared in a special way.
But we need some more permission in web server level, so we have to tune setting in web server level, they are
1 2 3 4 5 6 7 8 |
<system.webServer> <modules runAllManagedModulesForAllRequests="true" /> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2000000000" /> </requestFiltering> </security> </system.webServer> |
requestLimits :
It is a web server level setting. When request comes with ContentLength, i.e., it purely speaks about the URL length. It rejects the request with 404 error (Page not available) only if exceeds the limit which is specified in the property maxAllowedContentLength, it will not even get into WCF pipeline. So, this configuration setting is not related to WCF at all. Note that it limits the overall length of request; whatever is inside the request does not matter.
The Completed Version of web.config in a WCF should be
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<?xml version="1.0"?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5"/> </system.web> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="PowerTransmissionBinding" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="StreamedRequest" messageEncoding="Mtom"> <readerQuotas maxDepth="32" maxBytesPerRead="200000000" maxArrayLength="200000000" maxStringContentLength="200000000" /> </binding> </basicHttpBinding> </bindings> <services> <service name="DataTestingWCF.Service1"> <endpoint address="processData" binding="basicHttpBinding" bindingConfiguration="PowerTransmissionBinding" contract="DataTestingWCF.IService1" /> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpBinding" scheme="http" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true" /> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2000000000" /> </requestFiltering> </security> <directoryBrowse enabled="true"/> </system.webServer> </configuration> |
and the Completed Version of App.config in a Client Application should be
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" sendTimeout="00:10:00" messageEncoding="Mtom" transferMode="StreamedRequest" /> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:8099/Service1.svc/processData" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="SuperService.IService1" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel> </configuration> |
Here the endpoint address is refereeing the hosted address of a WCF, via this address the client application consumes the service from the WCF.
Conclusion: This article targets at understanding how efficiently we can transfer large amount of data from a Client application to WCF and vice versa. This article is intended for the beginner/intermediate level. I hope, this post will solve all your basic functionality implementation of WCF Configuration. Think Big… Start Small… Do Fast…