Transfer large files using WCF Service - Retrieve Error 413 - c#

I know this topic has been discused multiple times already, but unfortunately non of the provided solutions workd for me.
I try to transfer large files (up to 1.5 GB) from a client console application to a WCF service.
But I always get an HTTP error The remote server returned an unexpected response: (413) Request Entity Too Large. while transmitting the file content.
All information I found in the internet where about adding maxContentLength and similar configuration to web.config file.
But I assume I entered them at a wrong part from the web.config or so.
Edit 26.02.2020 18:35 (updated due to hints and new tests)
Based on the tipps from above I added some entries to config files and did some more tests.
In the mean time I found out a few things:
The number in web.config define the size in bit not in bytes as I read on severall pages
The number must be a valid int32 - so the maximum value is 2147483647
2147483647 bit are around 256 MByte - so it's understandable, that my testfile with around 400MB caused a problem
Overall, if it's not possible to transfer the large files - at least 20-30 MB should be possible.
For larger files I will find an other solution then.
To do easier tests I just created a new empty WCF service and a console application to test it.
You can find the complete sourcecode on Google Drive.
I included a 22MB test image as well, which doesn't work to transfer.
Different to my first problem, I now get a 404 error instead of a 413.
So somehow the IIS returns a 404 when the request is not matchable to a service instead of the previous 413.
A pretty strange behaviour for me.
The web.config and the app.config looks still the same as before (beside there is no entity framework stuff in).
Server web.config
<?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="mybinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<security mode="None"/>
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" bindingConfiguration="mybinding" />
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Client app.config
<?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="mybinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:53042/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="mybinding" contract="ServiceReference1.IService1"
name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
As I'm not a pro regarding web.config configuration, I assume, I just added the configuration in a wrong section of the XML.
Can anybody provide me some help, how my web.config need to look like, that I can transfer larger files.
Thanks in advance
Regards Markus

The service now publishes the endpoint using ProtocolMapping section, I suggest you name the binding and apply the configuration to the properties below.
<bindings>
<basicHttpBinding>
<binding name="mybinding" ... >
...
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" bindingConfiguration="mybinding"/>
</protocolMapping>
If it doesn’t work, we could publish the service by using the following style.
<system.serviceModel>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="basicHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
Feel free to let me know if the problem still exists.

Related

WCF client NTLM authentication returns 500

I have a problem with WinForms application connecting to WCF service using NTLM authentication.
<LongStory-optional>
Original application was written by me in 2005 as my first C# code. With small modifications it worked well. Web service was asmx with DataSets. Recently a time has come to upgrade it because of: performance issues and Windows 10 upgrade on client (Crystal Reports 10.5.37 upgrade was required to x64 and there is no official runtime download on SAP site).
I've rewrote it using WCF, .NET 4.8, replacing Crystal with library to create Excel files. In developer environment new version works well except 500 code. Rest and .NET Core was not considered (too difficult to explain; not technical reasons).
When user launched new version first immediate problem was "Access denied". Then it was started as administrator. Error code: "The application has failed to start because its side-by-side configuration is incorrect". Then I've tried to get more info in Event Viewer without success: there was no information. sxstrace tool raised access denied. After few days I've got it: I made a comment in config file containing national non-English characters. After removing comment an error 500 during connection has occured.
<\LongStory-optional>
Application makes a call to Verify service which just returns constant value 1.
Error message: "The content type text/html of the response message does not match the content type of the binding (text/xml; charset=utf-8).
If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 75 bytes of the response were:
The page cannot be displayed because an internal server error has occurred." .
Https was not used.
Strange thing is that after opening .svc once in IE the error have disappeared until workstation reboot. This proves that client and server are working correctly. In the same time old application doesn't have such an issue. Because of that I've tried to use "Web reference" instead of "Service reference". It appears that "Web reference" works correctly. Next thing I've tried different settings on the client side. I've found that "Service reference" works after this change: client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
With fiddler tool I've found that messages exchange are almost the same except final result: before change I have statuses 401/401/500, after change 401/401/200, the other differences are time and NTLM base64 value, nothing else.
I think that it is not a solution but only a workaround. Do you know how to handle correctly NTLM authentication with WCF?
Essential bits of my code and configuration:
var client = new ServiceClient();
client.ClientCredentials.Windows.ClientCredential.UserName = Dialog1.textBox1.Text;
client.ClientCredentials.Windows.ClientCredential.Domain = Dialog1.textBox2.Text;
client.ClientCredentials.Windows.ClientCredential.Password = Dialog1.textBox3.Text;
try
{
i = client.Verify().Status;
} ...
Configuration:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicEndpoint" sendTimeout="infinite" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://wro67zt2/AlsbWebServices/WindService/WindService.svc" binding="basicHttpBinding" bindingConfiguration="basicEndpoint" contract="WindService.IService" name="basicEndpoint"/>
</client>
</system.serviceModel>
I regard that server side configuration is unnecessary. It works well with Web reference so I can assume that everything is ok here. I've tried "Windows" instead "Ntlm" but problem remains the same, it changes string NTLM to Negotiate in request/response messages and also number of messages from 3 to 2 (401/500 or 401/200).
Edit - server configuration:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2"/>
<globalization culture="en-GB" requestEncoding="utf-8" responseEncoding="utf-8"/>
<pages controlRenderingCompatibilityVersion="4.0" clientIDMode="AutoID"/>
<identity impersonate="false" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBinding" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" realm="XXXXX"/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WindService.Behavior" name="WindLibrary.Service">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="basicBinding"
name="basicEndpoint"
bindingNamespace="http://XXXXX.com/services/prime/"
contract="WindLibrary.IService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WindService.Behavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="HttpBinding" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="false"/>
</system.webServer>
</configuration>

Implement Authentication in a WCF service (non ssl)

I have developed a .NET WCF service which uses basicHttp binding. This service is going to be hosted in IIS in an intranet and consumed by a non-Windows SAP PO client.
This service doesn't expose any sensitive information So I do not want to invest time on signing or encrypting messages. However, I also do not want the service to be accessed by anyone who knows the URL. so some form of authentication is required.
Can anyone please advise what would be the simplest way to authenticate my service?
UPDATE :
Thanks Keyur PATEL. I managed to host the service in IIS as per the link provided with security mode being set to "TransportCredentialOnly"
I enabled Basic Authentication in IIS
My windows client is able to subscribe the service however It receives below error when an operation is executed.
"The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="MY SERVER NAME"'.
Server Config
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="CustomAuthentication">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SecurityBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="SimpleService.UserNamePasswordAuthentification, App_Code/UserNameValidator"/>
</serviceCredentials>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SecurityBehavior" name="SimpleService.SimpleService">
<endpoint address="SimpleService" binding="basicHttpBinding" bindingConfiguration="CustomAuthentication" contract="SimpleService.ISimpleService"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Client Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ISimpleService">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://MYSERVERNAME:PORT/SimpleService.svc/SimpleService"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISimpleService"
contract="SimpleServiceDEV.ISimpleService" name="BasicHttpBinding_ISimpleService" />
</client>
</system.serviceModel>
</configuration>

Error with WCF. Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding

I'm new to building Web Services and WCF in general, although I've done well so far I've ran into The following issue issue I can't seem to get past.
Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding. Registered base address schemes are [].
I have my app.config set up as such
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WcfSoapServiceBinding">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WcfSoapServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="WcfSoapServiceBehavior" name="WcfSoapService.Service1">
<endpoint binding="wsHttpBinding" bindingConfiguration="WcfSoapServiceBinding"
contract="WcfSoapService.IService1" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
I set security mode to "None" so it uses HTTP instead of HTTPS and I also set the httpGetEnabled to true. I've tried some different options I've found online for some time, but none have helped so far. I'm using Ewald Hofman's example on how to use WCF to subscribe to TFS.
http://www.ewaldhofman.nl/post/2010/08/02/How-to-use-WCF-to-subscribe-to-the-TFS-2010-Event-Service-rolling-up-hours.aspx
I feel like I am close but this is the one thing I can't get past. My ultimate goal is to take the Soap Request from TFS and parse through its data. Being new to WCF and Web servers I'm unsure on what this error is actually telling me is wrong as well. So I have two questions.
1) What does this error mean is wrong? More specifically what does "Registered base address schemes are []" mean.
2) How could I go about fixing the error?
In your service section add base address or add address element for your endpoint.
<services>
<service behaviorConfiguration="WcfSoapServiceBehavior" name="WcfSoapService.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8182/MyService"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding" bindingConfiguration="WcfSoapServiceBinding"
contract="WcfSoapService.IService1" />
</service>

WCF service upload large file to ftp server

I am developing one windows phone application which upload images zip file to ftp server. But I can't upload it. It gives an error Remote server Not found
Here is my WCF application web.config
<?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" maxRequestLength="409600" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<!--<binding maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:10:00" closeTimeout="00:10:00">
<security mode="None" />
</binding>-->
<binding closeTimeout="01:30:00"
openTimeout="01:30:00" receiveTimeout="01:30:00" sendTimeout="01:30:00"
maxBufferSize="2147483646" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646">
<readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646"
maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646" />
<security mode="None">
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
Here is my ServiceReferences.ClientConfig
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647" closeTimeout="01:10:00"
openTimeout="01:10:00" receiveTimeout="01:10:00" sendTimeout="01:10:00" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xxx.xx.x.xxx/WebService/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="MyService.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
I have create two project one is windows phone application, second is wcf application. I am sending large byte[] array to wcf server which gives an error Remote server Notfound. It works perfectly when the byte[] size is small but fails when the size is large. I heard that we can send very large file to wcf service near about 4gb. Then where I was wrong? Is there any change I have to do in web.config? I have hosted my wcf service to IIS on local machine.
For sending large data over wcf you have two options:
You may manually break your data into pieces (or read by 2Kb from file for example) and transfer each piece separately. At server side you may save each piece in temp file. This method require some coding (control order of portions for example).
Another option is using transferMode="Streamed", but this mode have some restrictions.
Update
If you can't use Streamed mode for some reasons, you may create in your service some methods:
string BeginSendFile();
This method must gererate id (Guid for example) and return it to client. Also service may create a file in temporary storage with this name.
void SendFilePortion(string id, byte[] data);
You call this method and transfer a little data. Server may find temp file by id and write data to it.
void EndSentFile(string id, string originalName);
Call this method when transfer all data to rename your temp file and replace it in non-temp storage.

c# binding error in WCF

I am getting the following error when trying to access a WCF service.
Could not find a base address that matches scheme http for the endpoint with binding MetadataExchangeHttpBinding. Registered base address schemes are [https].
Here's my config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DefaultHttpBinding"
maxBufferSize="655360"
maxReceivedMessageSize="655360">
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://MySite.com/MyVirtualDir/"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="DefaultBehavior"
name="MyWcfService">
<endpoint address="http://MySite.com/MyVirtualDir/MyWcfService.svc"
binding="basicHttpBinding"
bindingConfiguration="DefaultHttpBinding"
contract="MyNamespace.IMyWcfService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="true"
policyVersion="Policy15"/>
<serviceDebug httpHelpPageEnabled="true"
includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And here's my .scv file
<%# ServiceHost Language="C#" Debug="true" Service="MyWcfService" Factory="MyWcfServiceHostFactory"%>
To give some more background that may or may not be helpful
The service works fine in our DEV environment. This error is only
occurring in our TEST and PROD environments. The only discernable
difference between environments that i am aware of is that TEST and PROD are using a
load balancer.
The service is hosted in IIS 5.1 on all environments
The service has been written in dot.net 3.5 and is activated by a
WebServiceHost factory
I have not specified https anywhere in my config file
SSL has NOT been enabled in IIS on any of the environments. Anonymous access has been enabled (security implementation will come later on).
Any help would be much appreciated as this is a complete show stopper for our project. I have throurghly searched the web for solutions to this problem, but nothing seems to relate to my my particular set up.
So for me, the fix for this issue was to remove the mex binding as per some of your suggestions. I also removed the servicemetadata section from the DefaultBehavior in config.
This fix only hides the original issue as I still have no idea why the mex binding was registered as https. But I can now consume my web service, even if i can't retrieve the metadata from it - that's not a problem in my case.
Here's the corrected config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DefaultHttpBinding"
maxBufferSize="655360"
maxReceivedMessageSize="655360">
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://MySite.com/MyVirtualDir/"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="DefaultBehavior"
name="MyWcfService">
<endpoint address="http://MySite.com/MyVirtualDir/MyWcfService.svc"
binding="basicHttpBinding"
bindingConfiguration="DefaultHttpBinding"
contract="MyNamespace.IMyWcfService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceDebug httpHelpPageEnabled="true"
includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Try enabling tracing on your service to check why things fail in your test/production environment. To enable tracing check this link
Are you sure that the MyWcfServiceHostFactory doesnt have any code related to configuration (i.e. building configuration via c# code)

Categories

Resources