basicHttpBinding maxBufferSize - c#

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;

Related

how to do authorization in WCF C#

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.

Marketing cloud SOAP API Retrieve request timeout exception

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"

Moving service configuration from the config to code

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
}
}
};

C# How to Update Visual Studio 2107 xxx.exe.config binding at runtime?

A xxx.exe.config file is created when I compile my C# web service code. However, I want to modify one of the bindings at run time. An example of the xxx.exe.config file generated by Visual Studio is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ContentService"
messageEncoding="Mtom" />
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
I want to add some parameters at run time to the binding named "BasicHttpBinding_ContentService" that are equivalent to manually coding:
<binding name="BasicHttpBinding_ContentService"
messageEncoding="Mtom"
maxBufferSize="5000000"
maxBufferPoolSize="524288"
maxReceivedMessageSize="2147483648"
transferMode="Streamed" />
I think the C# code to define the parameter settings looks like:
using System.ServiceModel;
BasicHttpBinding myBinding = new BasicHttpBinding("BasicHttpBinding_ContentService");
myBinding.MaxBufferSize = 5000000;
myBinding.MaxBufferPoolSize = 524288;
myBinding.MaxReceivedMessageSize = 2147483648;
myBinding.TransferMode = TransferMode.Streamed;
But I can't find a C# example (that works) that applies 'myBinding' to my Visual Studio .config file. The samples I do find reference classes like ServiceHost and ServiceClient that are undefined in my environment.
Note - I am using .NET 4.6.
I change quite alot of service endpoint on the fly but never use the config. I bind the webreference once then call it by code so i can change properties on the fly. Here's a very compact sample showing one that actually works
var binding = new BasicHttpBinding();
binding.CloseTimeout = new TimeSpan(0, 1, 30);
binding.OpenTimeout = new TimeSpan(0, 1, 30);
binding.ReceiveTimeout = new TimeSpan(0, 1, 30);
binding.SendTimeout = new TimeSpan(0, 1, 30);
binding.MaxReceivedMessageSize = 100000000;
binding.ReaderQuotas.MaxDepth = 2147483647;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
binding.ReaderQuotas.MaxArrayLength = 2147483647;
binding.ReaderQuotas.MaxBytesPerRead = 2147483647;
binding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
var endpoint = new EndpointAddress("http:\\example.com\MyService\Service.svc");
// MyService is the service object name that is in the web reference
var svc = new MyService.Service(binding, endpoint);
var clientData = svc.GetClientData("SomeClientName");
try something like this and let me know...
NTEGRAWSSOAPClient _wsProtheus = null; // NTEGRAWSSOAPClient is a SOAP client class generated by vs2017 on register webservice
var endpointConfiguration = NTEGRAWSSOAPClient.EndpointConfiguration.INTEGRAWSSOAP; //INTEGRAWSSOAP is a ConfigurationName of service
_wsProtheus = new NTEGRAWSSOAPClient(endpointConfiguration,new EndpointAddress("http://new address?wsdl", new SpnEndpointIdentity("your identi")));
BasicHttpBinding bind = (BasicHttpBinding)_wsProtheus.Endpoint.Binding;
bind.CloseTimeout = TimeSpan.Parse("02:00:00");
bind.OpenTimeout = TimeSpan.Parse("02:00:00");
bind.ReceiveTimeout = TimeSpan.Parse("02:00:00");
bind.SendTimeout = TimeSpan.Parse("02:00:00");
bind.MaxBufferPoolSize = Int32.MaxValue;
bind.MaxBufferSize = Int32.MaxValue;
bind.MaxReceivedMessageSize = Int32.MaxValue;
bind.ReaderQuotas.MaxDepth = 32;
bind.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
bind.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
bind.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;
bind.ReaderQuotas.MaxNameTableCharCount = Int32.MaxValue;
bind.Security.Mode = BasicHttpSecurityMode.None;

WCF client request returns bad request (400)

My client application use a WCF web service which is hosted in my local IIS. This web service use for upload an image. Once image size become bigger it gives bad request(400).
Client is configure to dynamically get the web service URL.
Client Code
string serviceUrl=GetUrl(); /* http://localhost:85/ImageUploaderService.svc */
TimeSpan timeOut = new TimeSpan(0, 30, 0);
EndpointAddress endPoint = new EndpointAddress(serviceUrl);
BasicHttpBinding binding = new BasicHttpBinding()
{
CloseTimeout = timeOut,
MaxReceivedMessageSize = 65536,
OpenTimeout = timeOut,
ReceiveTimeout = timeOut,
SendTimeout = timeOut,
MaxBufferSize = 65536,
MaxBufferPoolSize = 524288,
UseDefaultWebProxy = true,
};
binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 64000000,
MaxStringContentLength = 8192,
MaxDepth = 32,
MaxNameTableCharCount = 16384,
MaxBytesPerRead = 4096
};
client = new ImageUploaderServiceClient(binding, endPoint);
Web Service side
<basicHttpBinding>
<binding maxBufferSize="64000000" maxReceivedMessageSize="64000000" maxBufferPoolSize="64000000">
<readerQuotas maxDepth="64000000" maxStringContentLength="64000000" maxArrayLength="64000000" maxBytesPerRead="64000000" />
<security mode="None"/>
</binding>
</basicHttpBinding>
What is the wrong I am doing. Please guide me through the correct way.
You should increase MaxReceivedMessageSize on client side as well probably:
BasicHttpBinding binding = new BasicHttpBinding()
{
MaxReceivedMessageSize = 64000000,
MaxBufferSize = 64000000,
MaxBufferPoolSize = 64000000,
// .....
};
binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 64000000,
MaxStringContentLength = 64000000,
MaxDepth = 64000000,
MaxBytesPerRead = 64000000
};
I had the same problem once - the server and client binding configuration should be the same.

Categories

Resources