large file through WCF service - c#

Similar questions are flowing around and I looked at all of them. It appears none solve my issue.
-- UPDATE: --
I am trying to upload a document (pdf, doc, or whatever) to a database using WCF Service.
The call to the service looks like this:
using (var cw = new WCFClientWrapper<ICommonService>())
{
cw.Channel.DocumentInsert(content, filename, contentType);
}
Here is signature for the contract:
[OperationContract]
void DocumentInsert(byte[] content, string fileName, string contentType);
Please note that I am passing byte array for the content as this is what needs to be passed to store things in DB.
-- End of Update --
I can successfully upload a small file (couple kb). However, when I try to upload something larger (20kb), I get an Exception:
The formatter threw an exception while trying to deserialize the
message: Error in deserializing body of request message for operation
'DocumentInsert'. The maximum array length quota (16384) has been
exceeded while reading XML data. This quota may be increased by
changing the MaxArrayLength property on the XmlDictionaryReaderQuotas
object used when creating the XML reader. Line 1, position 31774.
The error seems to be obvious... just go and increase the MaxArrayLength. I have done that without any successful result. Below are the relevant parts from my web.configs
Client:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="SecureBehavior">
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="WSHttpBinding_Service" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="262144" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="2147483646" maxBytesPerRead="4096" maxNameTableCharCount="5242880" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://dev.svc.someurl.com/CommonService.svc"
binding="basicHttpBinding"
bindingConfiguration="WSHttpBinding_Service"
behaviorConfiguration="SecureBehavior"
contract="MyApp.Contracts.ServiceContracts.ICommonService"
name="MyApp.Contracts.ServiceContracts.ICommonService">
</endpoint>
</client>
</system.serviceModel>
Service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="MyBasicHttpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyApp.WCFServices.CommonService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="MyBasicHttpBinding"
contract="MyApp.Contracts.ServiceContracts.ICommonService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
<service name="MyApp.WCFServices.AccountService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="MyBasicHttpBinding"
contract="MyApp.Contracts.ServiceContracts.IAccountService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Attaching diagnostics shows:
Construct Service: no errors/warnings
Open Service: warning - Configuration evaluation context not found - No matching tag was found. Default endpoints added.
Listen at 'http://dev.svc.someurl.com/CommonService.svc' : no
errors/warnings
Processing message 1 : no errors/warnings
Processing Action 'http://tempuri.org/ICommonService/DocumentInsert'.
: throws exception that I wrote at the very beginning.
Any help is appreciated.

I have came across with the same exception a few months ago. To send/receive large data to/from WCF service you have to set transferMode="Streamed". When use transfermode as Buffered, it actually puts the entire file in memory before uploading/downloading. Therefore a large buffer is required on both the web client and the WCF service host.Whereas Streamed transfers can improve the scalability of a service by eliminating the need for large memory buffers. For more information on transfermode, see the MSDN article on TransferMode Enumeration

All right, after a day of struggling I finally found an issue.
I just had to make sure that the name of the tag in WCF web.config matches the namespace and the name of the service:
<service name="ServicesImplementation.WcfServices.CommonService">
Unfortunately it was not something that you guys would see based on the information that I provided.

Related

Consume WCF library functions from browser

I've a WCF library with some functions I use from Powershell and C# clients. Now I would like to use a couple of util functions directly from a browser but I'm not sure how to do.
First I added a webHttpBinding endpoint in the Web.config file, here is a slice
<services>
<service name="MI_lib.MainService">
<endpoint name="basic" address="" binding="basicHttpBinding" bindingConfiguration="MI_lib_http" contract="MI_lib.InterfaceMainService"></endpoint>
<endpoint name="web" address="web" binding="webHttpBinding" bindingConfiguration="MI_lib_web" contract="MI_lib.InterfaceMainService"></endpoint>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="MI_lib_http" />
</basicHttpBinding>
<webHttpBinding>
<binding name="MI_lib_web" crossDomainScriptAccessEnabled="true">
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
A simple function define for test purposes is this
[OperationContract]
[WebGet]
string GetData(int value);
Then if I connect to http://localhost/MI_lib/MI_lib.MainService.svc/web I get the following fault message
<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="de-CH">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Text>
</Reason>
</Fault>
Any hint on what to check or which other information to provide?
To define a web endpoint, you need, in addition to using the webHttpBinding, to add a web http behavior to your endpoint, as shown below:
<services>
<service name="MI_lib.MainService">
<endpoint name="basic" address="" binding="basicHttpBinding" bindingConfiguration="MI_lib_http" contract="MI_lib.InterfaceMainService"></endpoint>
<endpoint name="web"
address="web"
binding="webHttpBinding"
bindingConfiguration="MI_lib_web" contract="MI_lib.InterfaceMainService"
behaviorConfiguration="MyWeb">
</endpoint>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="MI_lib_http" />
</basicHttpBinding>
<webHttpBinding>
<binding name="MI_lib_web" crossDomainScriptAccessEnabled="true">
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="MyWeb">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
Also, the URL that you need to use also includes the method name, so you'll need to connect to
http://localhost/MI_lib/MI_lib.MainService.svc/web/GetData?value=123

The socket connection was aborted

I have a WCF service, that is hosted as a windows service, called by clients via proxy classes. The method in the proxy class looks like this:
public CustomerResponse GetCustomers(CustomerRequest request)
{
try
{
return Channel.GetCustomers(request);
}
catch (Exception ex)
{
throw ex;
}
}
GetCustomer presently returns me about 1000 records from my database. The problem is this:
I have ran my program on 4 different PCs, I'm only getting this error on 2 of them. The other 2 are fine, all with the same settings
On the 2 PCs with this problem, when I lowered the number of customer records in my database from 1000 to 200, the problem is resolved.
I have already max out all the settings that I know of in the config file
This is the exception message
The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9863281'.
I'm very certain it's not a time out issue as the exception is returned in less than a second.
This is my config file on the server
<services>
<service name="CustomerService" behaviorConfiguration="DefaultBehaviour">
<endpoint address="CommonService" binding="netTcpBinding" bindingConfiguration="customTcpBinding"
contract="ICustomerService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8542/CustomerService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehaviour">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
And this is the config file on the MVC project
<bindings>
<netTcpBinding>
<binding name="customTcpBinding" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<security mode="None"/>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
</binding>
</netTcpBinding>
</bindings>
<endpoint address="net.tcp://localhost:8542/CustomerService" binding="netTcpBinding" bindingConfiguration="customTcpBinding" contract="ICustomerService" name="NetTcpBinding_CustomerService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>

WCF callback timeout and Visual Studio catastrophic failure

A kind of stupid error, but this happened when I wanted to call client by server-side-service (WCF Duplex):
The message could not be transferred within the allotted wcf callback timeout of 00:01:00, There was no space available in the reliable channel's transfer window
Also something mysterious happened too. In the login method when I called service if user and password be wrong I find sender-callback and then call GetError method on sender to show logical error like "User is wrong". This works well, but if user and password is correct and have access, I got that error (same for all other client-side methods - in all these methods I send more data than simple strings, I was send geterror) !
Edit 2: As I say in most of the callback methods, I was send data like data-context (LINQ to SQL) data-class (list or single row). So might this be my problem or not!
(But this isn't my first time, using WCF-duplex, also with send data-struct in callback methods , I'm so astounding.)
Also after that error I got this error on,
Screen unable to process request from service http://server:15450/service.svc catastrophic failure
Edit 3:
Service configuration:
<system.serviceModel>
<services>
<service name="ContactServer.Business.ContactService"
behaviorConfiguration="ServiceBehavior">
<endpoint address=""
binding="wsDualHttpBinding"
contract="ContactServer.Business.IContactService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
name="MexBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
and Client Config
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_ContactService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1408/ContactService.svc"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ContactService"
contract="ServiceReference.ContactService" name="WSDualHttpBinding_ContactService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
More information: I use .NET 3.5 and Visual Studio 2010. Also after rising timeout on the client side I still got the same error, with 00:01:00 Time. Why did this happen?
The problem is concerning transfer of entities from a WCF-service.
For example, we have this database model:
Entity Framework:
public Item GetItem(int id)
{
var se = new SampleEntities();
return se.Items.FirstOrDefault(i => i.Id == id);
}
The code doesn't seem to be wrong, but in reality it will return the item with all related items.
var s = new SampleServiceClient();
var item = s.GetItem(1);
Assert.AreEqual(item.RelatedItems.Any(), true); //equal
It is especially dangerous if we have many-to-many relations in the database.
So lazy loading should be disabled (you can disable them just before the return):
var se = new SampleEntities();
se.ContextOptions.LazyLoadingEnabled = false;
return se.Items.FirstOrDefault(i => i.Id == id);
Linq to SQL
public Item GetItem(int id)
{
var dc = new DataClasses1DataContext();
return dc.Items.FirstOrDefault(i => i.Id == id);
}
We have an exception:
There was an error while trying to serialize parameter :GetItemResult. The InnerException message was 'Object graph for type 'WebApplication1.RelatedItem' contains cycles and cannot be serialized if reference tracking is disabled.'.
You must open DataContext diagramm and set Properties->SerializationMode->Unindirectional. Here is a more complete explanation.

WCF inner exception message "A registration already exists for URI 'net.tcp://....' " when trying to support a dual LAN from a WCF service

I have a self-hosted WCF service which is using the net.tcp protocol for an endpoint and it works fine on a PC with a normal LAN card.
However, I want to support PCs which have dual LAN cards and this gives me problems. I have assigned different IP addresses to the two cards (192.168.1.1 and 193.168.1.1). I then changed my app.config file to try to support the dual LAN by adding a second endpoint for the WCF service, using the second IP address. (My WCF client can handle selecting which of the two endpoint addresses to use.)
When I run the service, I get the following error message:
The ChannelDispatcher at 'net.tcp://193.168.1.1:59301/MyClientService' with contract(s) "'IMyClientService'" is unable to open its IChannelListener.
Additional information from inner exception:
A registration already exists for URI 'net.tcp://193.168.1.1:59301/MyClientService'.
Note: If I change the port # on the second endpoint in the app.config file (e.g. if i use 193.168.1.1:59302), the service starts up fine. That's a workaround, but it would be useful to be able to use the same port for both LANs, if possible.
Oh, and I tried portSharingEnabled on the binding (with the Net.TCP Port Sharing Service running) but that didn't help.
Thanks in advance...
My app.config file looks like this:
<!-- Information about assembly binding and garbage collection -->
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
<system.serviceModel>
<services>
<service name ="MyNamespace.MyClientService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<!-- Using TCP -->
<add baseAddress = "net.tcp://localhost:59301/MyClientService/" />
</baseAddresses>
</host>
<!-- Using TCP -->
<endpoint
address="net.tcp://192.168.1.1:59301/MyClientService"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IMyClientService"
contract="MyNamespace.IMyClientService"
/>
<endpoint
address="net.tcp://193.168.1.1:59301/MyClientService"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IMyClientService"
contract="MyNamespace.IMyClientService"
/>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint
address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<bindings>
<!-- ==================================================================================== -->
<!-- TCP/IP bindings -->
<netTcpBinding>
<binding name="NetTcpBinding_IMyClientService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="2147483647" maxConnections="10"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<!-- <serviceMetadata httpGetEnabled="True"/> -->
<serviceMetadata/>
<!-- 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>
</system.serviceModel>
What does "localhost" resolve to?
Looks like you're adding a base address on "localhost" and two additional endpoints, one of which will probably conflict with localhost.
Try removing the base address, see if that makes a difference...
It looks like the following section is duplicated:
<endpoint
address="net.tcp://192.168.1.1:59301/MyClientService"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IMyClientService"
contract="MyNamespace.IMyClientService"
/>
Just try removing one of then

WCF wsHttpBinding 'algorithmSuite' cannot be parsed error

I am using VSTS 2008 + C# + .Net 3.0. I am using self-hosted WCF. When executing the following statement (host.Open()), there is the following binding not found error. I have posted my whole app.config file, any ideas what is wrong?
ServiceHost host = new ServiceHost(typeof(MyWCFService));
host.Open();
Error message,
The value of the property 'algorithmSuite' cannot be parsed. The error is: The value 'Aes128' is not a valid instance of type 'System.ServiceModel.Security.SecurityAlgorithmSuite'.
EDIT1: I have changed the algorithm suit option value to Default, but met with a new error when executing Open(), error message is, any ideas what is wrong,
Binding validation failed because the WSHttpBinding does not support reliable sessions over transport security (HTTPS). The channel factory or service host could not be opened. Use message security for secure reliable messaging over HTTP.
Full app.config,
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MyBinding"
closeTimeout="00:00:10"
openTimeout="00:00:20"
receiveTimeout="00:00:30"
sendTimeout="00:00:40"
bypassProxyOnLocal="false"
transactionFlow="false"
hostNameComparisonMode="WeakWildcard"
maxReceivedMessageSize="100000000"
messageEncoding="Mtom"
proxyAddress="http://foo/bar"
textEncoding="utf-16"
useDefaultWebProxy="false">
<reliableSession
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Digest"
proxyCredentialType="None"
realm="someRealm" />
<message clientCredentialType="Windows"
negotiateServiceCredential="false"
algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="MyWCFService"
behaviorConfiguration="mexServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="https://localhost:9090/MyService"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyBinding" contract="IMyService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexServiceBehavior">
<serviceMetadata httpsGetEnabled="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
thanks in advance,
George
You need to update your service behavior, too, if you change the MEX endpoint from http to https - you need to enable the httpsGetEnabled setting (not the httpGetEnabled):
<behaviors>
<serviceBehaviors>
<behavior name="mexServiceBehavior">
<serviceMetadata httpsGetEnabled="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
UPDATE:
George, check out this MSDN link - there is no "Aes128" algorithm - you must pick one of the existing ones.
UPDATE 2:
Can you try this config - reduce to the max! :-)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MyBinding"
maxReceivedMessageSize="100000000"
messageEncoding="Mtom"
proxyAddress="http://foo/bar"
textEncoding="utf-16"
useDefaultWebProxy="false">
<reliableSession enabled="false" />
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="MyWCFService"
behaviorConfiguration="mexServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="https://localhost:9090/MyService"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyBinding" contract="IMyService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexServiceBehavior">
<serviceMetadata httpsGetEnabled="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Can you start up your service,and can you add service reference from Visual Studio?
UPDATE 3:
George, I'd recommend you have a look at those security-related links and get some feel for what you really need and want - and how to achieve it.
WCF Security Guide
WCF Security Fundamentals
Fundamentals of WCF Security
MSDN Webcast Series "WCF Top To Bottom"
esp. Episode 10 - Security Fundamentals
Marc
The error message is correct, you don't get reliable messages over WSHttp, you need to use a custom binding and protocol.

Categories

Resources