I am trying to download the subscribers from marketing cloud using the SOAP API and it throws the following exception after couple of iterations.
It does not fail consistently. Sometimes it completes 50 iterations and fails and sometimes it fails after 5 or 10 iterations.
Here is the code I am using to make the retrieve request:
public List<Subscriber> GetSubscribers(string RequestId = null)
{
string message = string.Empty;
_lstSubscribers = new List<Subscriber>();
SoapClient client = new SoapClient();
client.ClientCredentials.UserName.UserName = _username;
client.ClientCredentials.UserName.Password = _password;
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.ObjectType = "Subscriber";
string[] props = { "Client.ID", "CreatedDate", "EmailAddress", "EmailTypePreference", "ID", "PartnerKey", "SubscriberKey", "UnsubscribedDate" };
retrieveRequest.Properties = props;
retrieveRequest.ClientIDs = new ClientID[] { _clientID };
//retrieveRequest.QueryAllAccounts = true;
//retrieveRequest.QueryAllAccountsSpecified = true;
String requestId = RequestId;
String response = string.Empty;
int tryCount = 0;
try
{
RunRetrieveRequest(client, out requestId, out response, retrieveRequest);
}
catch (Exception ex)
{
if (response == "MoreDataAvailable")
{
tryCount++;
if (tryCount <= 10)
{
}
retrieveRequest.ContinueRequest = requestId;
RunRetrieveRequest(client, out requestId, out response, retrieveRequest);
}
}
return _lstSubscribers;
}
private void RunRetrieveRequest(SoapClient client, out string RequestID, out string Response, RetrieveRequest Request)
{
List<Subscriber> lstSubscribers = new List<Subscriber>();
APIObject[] results = null;
do
{
Response = client.Retrieve(Request, out RequestID, out results);
Subscriber subscriber = null;
if (Response != null && results != null)
{
foreach (var result in results)
{
subscriber = (Subscriber)result;
_lstSubscribers.Add(subscriber);
}
}
Request = new RetrieveRequest();
Request.ContinueRequest = RequestID;
} while (Response == "MoreDataAvailable");
}
Here is the config. I have tried changing the timeout attributes from 30 to 59, but this didn't help.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="SoapBinding">
<security mode="Transport" />
</binding>
<binding name="SoapBinding1" />
</basicHttpBinding>
<customBinding>
<binding name="SoapBinding" closeTimeout="00:59:00" openTimeout="00:59:00" receiveTimeout="00:59:00" sendTimeout="00:59:00">
<security authenticationMode="UserNameOverTransport">
<secureConversationBootstrap />
</security>
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
<httpsTransport maxReceivedMessageSize="655360000" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://mySubDomain.soap.marketingcloudapis.com/Service.asmx"
binding="customBinding" bindingConfiguration="SoapBinding"
contract="sfmc.Soap" name="Soap" />
</client>
</system.serviceModel>
I will appreciate any help or suggestion. Thanks in advance.
I have been able to resolve this issue and posting the answer as it may help someone else struggling with a similar issue. The Salesforce marketing cloud API (both SOAP and REST) has stopped supporting the default TLS 1.0 protocol. So I needed to add the following code before I sent any request to the API.
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls;
The following link has more explained insights on the same.
WCF Error "This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case"
Related
i have a WCF service, i can connect to it, but i cannot call it's method. the exception i get is 'The operation timed out.
but i can call it throw SoapUI very fast and without any error. in soap-ui i should add authorization to make it work :
what i did to solve the problem is:
-adding credentials :
communicationClient.ClientCredentials.UserName.UserName = "XXXX";
communicationClient.ClientCredentials.UserName.Password = "XXXX";
-increasing time out :
communicationClient.Endpoint.Binding.SendTimeout = TimeSpan.FromMinutes(5);
communicationClient.Endpoint.Binding.ReceiveTimeout = TimeSpan.FromMinutes(5);
-doing the same in app.config
they didn't work.
where i create and start the service (in client app) is :
private bool StartService()
{
BasicHttpBinding hb = new BasicHttpBinding()
{
CloseTimeout = new TimeSpan(0, 1, 0, 0),
//MaxBufferSize = 4096,
OpenTimeout = new TimeSpan(0, 1, 0, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0, 0),
SendTimeout = new TimeSpan(0, 1, 0, 0),
};
EndpointAddressBuilder epb = new EndpointAddressBuilder()
{
Uri = new System.Uri("....myServiceUri....")
};
try
{
communicationClient = new SendLetterServiceClient(hb, epb.ToEndpointAddress());
}
catch (EndpointNotFoundException en) { throw en; }
catch (CommunicationException ce) { throw ce; }
communicationClient.ClientCredentials.UserName.UserName = "xxxxxxxx";
communicationClient.ClientCredentials.UserName.Password = "xxxxxxxx";
communicationClient.Endpoint.Binding.SendTimeout = TimeSpan.FromMinutes(5);
communicationClient.Endpoint.Binding.ReceiveTimeout = TimeSpan.FromMinutes(5);
//communicationClient.
if (communicationClient.State != CommunicationState.Opened && communicationClient.State != CommunicationState.Opening)
communicationClient.OpenAsync();
return true;
}
where i use it is :
public async Task<string> SendLetter(string nationalCode, string fileName, byte[] attachments)
{
if (!serviceHasBeenStarted)
{
try{serviceHasBeenStarted = StartService();}
catch{throw new Exception("service has not been started, and can not restart it");}
}
string orgUserName = "XXXXXX";
string orgPassword = "XXXXXX";
string orgCode = "XXXX";
sendLetterAttach attachedLetter = new sendLetterAttach()
{
fileData = attachments,
fileName = fileName
};
try
{
var response1 = Task<getLetterTypeResponse>.Run(() =>
{
return communicationClient.getLetterTypeAsync(
orgCode, orgUserName, orgPassword);
}).Result;
return response1.#return[0];
}
catch(Exception e1)
{
Console.WriteLine("error: \n\t" + e1.Message);
}
return "";
}
when it calls the method, it waits for a minute, then throws exception.
i had added the service through 'add service reference' using visual studio in my .netCore solution.
...Ah! when i add the service, i get following warning:
Warning:Warning: No endpoints compatible with .Net Core apps were found.
This is because core does not support Message:
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
The above binding configuration is not supported in core,if a service with the above binding configuration is added to the core, an error will be reported:
Core only supports None, Transport:
About core's support for WCF, you can refer to this link:
https://github.com/dotnet/wcf/tree/master/release-notes
solution
You need to change the Message of the server to Transport:
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Username and password need to be added when the client is calling:
Client.ClientCredentials.UserName.UserName = "test";
Client.ClientCredentials.UserName.Password = "tset";
Feel free to let me know if the problem persists.
UPDATE
You can directly generate proxy classes through the Svcutil command:
Access the singlewsdl of the WCF service through the browser, and then save it locally.
Use Svcutil command to generate proxy class and configuration file.
Finally add them to your project.
I have the following configuration in my app.config:
<bindings>
<customBinding>
<binding name="myBinding">
<textMessageEncoding messageVersion="Soap12"/>
<httpTransport/>
</binding>
</customBinding>
<wsHttpBinding>
<binding name="myBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="/../" binding="wsHttpBinding" bindingConfiguration="myBinding" contract="myContract" name="myName"/>
</client>
Using this configuration the service works as expected.
For several reasons i can't use the app.config file in the production environment, so i want to define the bindings in c# instead. I did the following:
var binding = new BasicHttpBinding();
var address = new EndpointAddress(url);
binding.Security = new BasicHttpSecurity() { Mode = BasicHttpSecurityMode.Transport };
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
var client = new MyClient(binding, address);
This works for the first part, but then fails on using an incorrect message version. I can see this is defined in the custombinding, but i'm not sure how to translate this binding to my code. I did try quite a lot, but with no result so far.
Does anyone know how to do this?
I would recommend you to leverage the ConfigurationChannelFactory<TChannel> class to configure your client using XML configuration from a source other than an app.config file (e.g. an XML string read from a database, from a resource in your executable, or from some other custom source).
The XML format is IMHO easier to read and maintain than a configuration built using code.
To do this, the steps are as follows:
Get a string with your XML configuration data, e.g.:
string configurationData = #"<configuration>
<system.serviceModel>
...
";
Save it to a temporary file:
var tempFileName = Path.GetTempFileName();
File.WriteAllText(tempFileName, configurationData);
Generate a System.Configuration.Configuration object from the temp file:
var filemap = new ExeConfigurationFileMap
{
ExeConfigFilename = tempFileName
};
var config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
Create a ChannelFactory<TChannel> from the configuration:
var channelFactory = new ConfigurationChannelFactory<TChannel>(endpointConfigurationName, config, remoteAddress);
Once you've created your ChannelFactory<TChannel>, you can delete the temporary file.
You are using BasicHttpBinding instead of CustomBinding
you should do something like this:
var binding = new CustomBinding();
TextMessageEncodingBindingElement textBindingElement = new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
WriteEncoding = System.Text.Encoding.UTF8,
ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max
};
binding.Elements.Add(textBindingElement);
But, if you are using .net core you might have issues with this, because there is an open issue for this on GitHub: https://github.com/dotnet/wcf/issues/2711
It seems you are using wshttpbinding.
You could try the code below.Please change to your address and contract.
WSHttpBinding wsbinding = new WSHttpBinding();
wsbinding.MaxBufferPoolSize = 2147483647;
wsbinding.MaxReceivedMessageSize = 2147483647;
wsbinding.MessageEncoding = WSMessageEncoding.Mtom;
wsbinding.TextEncoding = Encoding.UTF8;
wsbinding.Security.Mode = SecurityMode.Transport;
wsbinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
using (ChannelFactory<ICalculatorService> channelFacoty = new ChannelFactory<ICalculatorService>(wsbinding, new EndpointAddress("http://localhost")))
{
ICalculatorService cal = channelFacoty.CreateChannel();
Console.WriteLine( cal.Add(1, 3));
Console.Read();
}
Try the WebHttBinding:
binding = new WebHttpBinding
{
TransferMode = TransferMode.Buffered,
ReceiveTimeout = TimeSpan.FromMinutes(1),
SendTimeout = TimeSpan.FromMinutes(1),
MaxReceivedMessageSize = 2147483647,
MaxBufferPoolSize = 2147483647,
ReaderQuotas =
{
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxNameTableCharCount = 2147483647
},
Security = new WebHttpSecurity()
{
Mode = WebHttpSecurityMode.Transport,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.Ntlm
}
}
};
I am trying to create WCF RESTful Service with WebHttpBinding without https. In this below is the code for IUserMgmtService and
[ServiceContract]
public interface IUserMgmtService
{
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest, UriTemplate = "AddUsers")]
ResponseUser AddUsers(RequestUser requestUser);
}
Below is the code for UserMgmtService.svc to add user to the SQL Database
[ServiceBehavior(Namespace = "http://localhost:30158/Services/")]
public class UserMgmtService : IUserMgmtService
{
public ResponseUser AddUsers(RequestUser objData)
{
ResponseUser response = new ResponseUser();
try
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["WCFData"].ConnectionString))
{
connection.Open();
string sql = "WCFData_Insert_User";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.Add("#UserKey", SqlDbType.BigInt).Value = objData.UserKey;
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar, 100).Value = objData.FirstName;
cmd.Parameters.Add("#LastName", SqlDbType.VarChar, 100).Value = objData.LastName;
cmd.Parameters.Add("#EmailAddress", SqlDbType.VarChar, 255).Value = objData.EmailAddress;
cmd.Parameters.Add("#UserType", SqlDbType.VarChar, 20).Value = objData.UserType;
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
}
response.Status = "Success - Record Inserted Successfully";
response.Success = true;
}
catch (Exception ex)
{
response.Status = "Failure - " + ex.InnerException;
response.Success = true;
}
return response;
}
}
Below is the configuration of Web.Config for the RESTful Service
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="crossOriginResourceSharingBehavior" type="WCFServices.EnableCrossOriginResourceSharingBehavior, WCFServices" />
</behaviorExtensions>
</extensions>
<bindings>
<basicHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<!--<readerQuotas maxDepth="200" maxStringContentLength="8388608" maxArrayLength="16384" maxBytesPerRead="2147483647" maxNameTableCharCount="16384" />-->
<readerQuotas maxDepth="200" maxStringContentLength="8388608" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport" />
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="RestBindingConfiguration" maxReceivedMessageSize="2147483647" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" maxBufferPoolSize="2147483647">
<!--<security mode="Transport">
--><!--<transport clientCredentialType="None" proxyCredentialType="None"></transport>--><!--
</security>-->
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="WCFServices.UserMgmtService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:30158/Services/" />
</baseAddresses>
</host>
<endpoint address="WCFServices.UserMgmtService" behaviorConfiguration="RestBehavior" binding="webHttpBinding" bindingConfiguration="RestBindingConfiguration" contract="WCFServices.IUserMgmtService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RestBehavior">
<webHttp />
</behavior>
<behavior name="jsonBehavior">
<webHttp />
<crossOriginResourceSharingBehavior />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Below is the calling code in Client
RequestUser requestUser = new RequestUser();
requestUser.UserKey = user.UserKey;
requestUser.FirstName = user.FirstName;
requestUser.LastName = user.LastName;
requestUser.EmailAddress = user.EmailAddress;
requestUser.UserType = user.UserType;
string url = "http://localhost:30158/Services/UserMgmtService.svc/";
string requestMethod = "AddUsers";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(url + requestMethod));
req.ContentType = "application/json";
req.Method = "POST"; //GET, POST etc
var contentBytes = JSONHelper.SerializeToBytes<RequestUser>(requestUser);
using (Stream dataStream = req.GetRequestStream())
{
// Write the data to the request stream.
dataStream.Write(contentBytes, 0, contentBytes.Length);
}
HttpWebResponse webResponse = (HttpWebResponse)req.GetResponse();
//Set the status code
string resStatus = string.Empty;
using (StreamReader responseStreamReader = new StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8, true))
{
string content = responseStreamReader.ReadToEnd();
response = JSONHelper.Deserialize<ResponseUser>(content);
}
Below is the code for RequestUser
[DataContract(Namespace = "http://localhost:30158/Services/RequestUser/")]
public class RequestUser
{
[DataMember(Order = 1)]
public long? UserKey { get; set; }
[DataMember(Order = 2)]
public string FirstName { get; set; }
[DataMember(Order = 3)]
public string LastName { get; set; }
[DataMember(Order = 4)]
public string EmailAddress { get; set; }
[DataMember(Order = 5)]
public string UserType { get; set; }
}
Below is the code for ResponseUser
[DataContract(Namespace = "http://localhost:30158/Services/ResponseUser/")]
public class ResponseUser
{
[DataMember]
public string Status { get; set; }
[DataMember]
public bool Success { get; set; }
}
Below is the WSDL file content
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
wssecurity-utility-1.0.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:tns="http://localhost:30158/Services/"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:i0="http://tempuri.org/"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
name="UserMgmtService" targetNamespace="http://localhost:30158/Services/">
<wsdl:import namespace="http://tempuri.org/"
location="http://localhost:30158/Services/UserMgmtService.svc?
wsdl=wsdl0"/>
<wsdl:types/>
<wsdl:service name="UserMgmtService"/>
</wsdl:definitions>
When I run the code in Client, it throws error at HttpWebResponse webResponse = (HttpWebResponse)req.GetResponse(); as below
An exception of type 'System.Net.WebException' occurred in Service.dll but was not handled in user code
Additional information: The remote server returned an error: (404) Not Found.
I followed this post (WCF - How to Increase Message Size Quota) and set the MaxBuffer size the largest size it can be and I still get the error. What else could I change?
I used Fiddler to view the response and it is 67,934 bytes. Below is the binding.
<basicHttpBinding>
<binding name="MCPClaimsService_InterfaceSOAP"
maxReceivedMessageSize="21474836470"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="32"
maxArrayLength="2147483647"
maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
This code has a custom binding. I did not write it.
public static CustomBinding HttpsSSLBinding()
{
var textmessageEncoding = new TextMessageEncodingBindingElement();
textmessageEncoding.WriteEncoding = Encoding.UTF8;
textmessageEncoding.MessageVersion = MessageVersion.Soap11;
MessageSecurityVersion securityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
AsymmetricSecurityBindingElement bindingElement =
(AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(securityVersion, true);
bindingElement.SetKeyDerivation(false);
bindingElement.EnableUnsecuredResponse = true;
X509SecurityTokenParameters istp = bindingElement.InitiatorTokenParameters as X509SecurityTokenParameters;
if (istp != null)
{
istp.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
istp.InclusionMode = SecurityTokenInclusionMode.Never;
}
X509SecurityTokenParameters rstp = bindingElement.RecipientTokenParameters as X509SecurityTokenParameters;
if (rstp != null)
{
rstp.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
rstp.InclusionMode = SecurityTokenInclusionMode.Never;
}
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
return new CustomBinding(bindingElement, textmessageEncoding, transport);
}
}
After I realized it had a custom binding in addition to the binding statement in app.config I added the lines below to the custom binding code and that solved the problem. Hopefully this waste of my time will help someone in the future.
transport.MaxBufferSize = 2147483647;
transport.MaxReceivedMessageSize = 2147483647;
transport.MaxBufferPoolSize = 2147483647;
When I transfer a file about 50Mb over HTTP sometimes I get this error:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
First of all I couldn't find any solution under http://stackoverflow.com.
Any clue what I have to improve/change?
app.config:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_MyDomainServicesoap" closeTimeout="00:03:00" openTimeout="00:04:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="50000000" maxBufferPoolSize="50000000" maxReceivedMessageSize="50000000" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="64" maxStringContentLength="16384" maxArrayLength="32768" maxBytesPerRead="8192" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
<binding name="BasicHttpBinding_MyAuthenticationDomainServicesoap" closeTimeout="00:03:00" openTimeout="00:04:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="50000000" maxBufferPoolSize="50000000" maxReceivedMessageSize="50000000" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="64" maxStringContentLength="16384" maxArrayLength="32768" maxBytesPerRead="8192" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
code:
private void FinishWebRequest(IAsyncResult result)
{
// Assign values to these objects here so that they can be referenced in the finally block
Stream remoteStream = null;
Stream localStream = null;
WebResponse response = null;
try
{
response = request.EndGetResponse(result);
if (response != null)
{
// Once the WebResponse object has been retrieved, get the stream object associated with the response's data
remoteStream = response.GetResponseStream();
// Create the local file
string pathToSaveFile = Path.Combine(FileManager.GetFolderContent(), FileView.Filename);
localStream = File.Create(pathToSaveFile);
WinAPI.SYSTEM_INFO sysinfo = new WinAPI.SYSTEM_INFO();
WinAPI.GetSystemInfo(ref sysinfo);
// Allocate a buffer
byte[] buffer = new byte[int.Parse(sysinfo.dwPageSize.ToString())];
int bytesRead;
// Simple do/while loop to read from stream until no bytes are returned
do
{
// Read data (up to 1k) from the stream
bytesRead = remoteStream.Read(buffer, 0, buffer.Length);
// Write the data to the local file
localStream.Write(buffer, 0, bytesRead);
// Increment total bytes processed
BytesProcessed += bytesRead;
} while (bytesRead > 0);
FileView.Downloaded = DateTime.Now;
if (BytesProcessed > 0)
{
FileView.IsSuccess = true;
FileView.IsDownloading = false;
}
else
{
FileView.IsSuccess = false;
FileView.IsDownloading = false;
}
}
}
catch (Exception ex)
{
#region Error
LogEntry l = new LogEntry();
l.Message = string.Format("{0}", ex.Message);
l.Title = "FinishWebRequest() Error";
l.Categories.Add(Category.General);
l.Priority = Priority.Highest;
if (ex.InnerException != null) l.ExtendedProperties.Add("InnerException", ex.InnerException.Message);
CustomLogger.CustomLogger.WriteErrorLog(l);
#endregion
}
finally
{
// Close the response and streams objects here to make sure they're closed even if an exception is thrown at some point
if (response != null) response.Close();
if (remoteStream != null) remoteStream.Close();
if (localStream != null) localStream.Close();
}
}
I am not sure if it is a solution for all cases.
But when I reduced the number of parallel connections to the server to download big files from 3 to 2 only there are no error.
(Early I used 3 parallel connections.)
I ran into a similar issue and was able to resolve it by adding a behaviors section to my web.config which tells the data contract serializer to override the default 64kb size limit.
<behaviors>
<endpointBehaviors>
<behavior>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
</behaviors>
Also, after adding in the config I started getting an error on the client side that was the same issue, you’ll need to add this config to both your service and client side.