C# wcf protobuf client - c#

I have a Protobuf WCF Service. Everything works fine when I consume it.
Data is Protobuf and everythings good.
But now I want to use the same class I use with the Protobuf attributes
without Protobuf. How can someone achive that?
I want to consume the service that has Protobuf implemented without protobuf.
And I dont want to change/add another exact class just to have both ways.
EDIT:
var customBinding = new System.ServiceModel.Channels.CustomBinding();
customBinding.Elements.Add(new System.ServiceModel.Channels.TextMessageEncodingBindingElement(System.ServiceModel.Channels.MessageVersion.Soap11, System.Text.Encoding.UTF8));
var httpsBindingElmnt = new System.ServiceModel.Channels.HttpsTransportBindingElement();
httpsBindingElmnt.MaxReceivedMessageSize = 2147483647;
httpsBindingElmnt.UseDefaultWebProxy = true;
//httpsBindingElmnt.ReaderQuotas.MaxStringContentLength = 2147483647;
//httpsBindingElmnt.ReaderQuotas.MaxBytesPerRead = 2147483647;
//httpsBindingElmnt.ReaderQuotas.MaxArrayLength = 2147483647;
//httpsBindingElmnt.ReaderQuotas.MaxDepth = 2147483647;
//httpsBindingElmnt.ReaderQuotas.MaxNameTableCharCount = 2147483647;
//httpsBindingElmnt.ReceiveTimeout = new TimeSpan(0, 30, 0);
//httpsBindingElmnt.Name = "VaultBasicHttpBinding";
httpsBindingElmnt.MaxBufferSize = 2147483647;
httpsBindingElmnt.MaxBufferPoolSize = 2147483647;
//httpsBindingElmnt.ReceiveTimeout = new TimeSpan(0, 30, 0);
customBinding.Elements.Add(httpsBindingElmnt);
//string address = "https://adress/MobileService.svc";
//Uri baseAddress = new Uri(address);
//ServiceHost host = new ServiceHost(MobileService.MobileServiceClient), baseAddress);
//ChannelFactory<MobileService.MobileServiceClient> factory = new ChannelFactory<MobileService.MobileServiceClient>(customBinding, address);
//MobileService.MobileServiceClient client = factory.CreateChannel();
MobileService.MobileServiceClient client = new MobileService.MobileServiceClient(customBinding,
new EndpointAddress("https://adress/MobileService.svc"));
//MobileService.MobileServiceClient client = new MobileService.MobileServiceClient(customBinding,
// new EndpointAddress("http://127.0.0.1:4501/MobileService.svc"));
client.Endpoint.EndpointBehaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
And after that iam using the client objects functions.

Related

WCF Client Sign Soap Message with Smart Card

I have forms application with service reference by using CustomBinding for signing soap request (Only need soap body will be signed). If I try to sign request with private key included pfx wcf client succesfully sign Basic256Sha256Rsa15.
Succesfull case below:
private CustomBinding GetCustomHttpBinding()
{
CustomBinding binding = new CustomBinding();
// Open and Close = 20s
binding.OpenTimeout = new TimeSpan(0, 0, 20);
binding.CloseTimeout = new TimeSpan(0, 0, 20);
// Send and Receive = 300s
binding.SendTimeout = new TimeSpan(0, 5, 0);
binding.ReceiveTimeout = new TimeSpan(0, 5, 0);
// ++ Setting security binding ++
var param = new X509SecurityTokenParameters();
param.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
param.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
param.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
param.RequireDerivedKeys = false;
var userNameToken = new UserNameSecurityTokenParameters();
userNameToken.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
var securityElement = new AsymmetricSecurityBindingElement();
securityElement.EnableUnsecuredResponse = true;
securityElement.IncludeTimestamp = true;
securityElement.RecipientTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.Never);
securityElement.InitiatorTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.AlwaysToRecipient);
securityElement.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15;
securityElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
securityElement.SetKeyDerivation(false);
securityElement.EndpointSupportingTokenParameters.Signed.Add(param);
//securityElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
binding.Elements.Add(securityElement);
// ++ Setting message encoding binding ++
var encodingElement = new TextMessageEncodingBindingElement();
encodingElement.MessageVersion = MessageVersion.Soap12;
encodingElement.WriteEncoding = Encoding.UTF8;
//encodingElement.MaxReadPoolSize = 50000000;
//encodingElement.MaxWritePoolSize = 50000000;
encodingElement.ReaderQuotas.MaxArrayLength = 50000000;
encodingElement.ReaderQuotas.MaxStringContentLength = 50000000;
binding.Elements.Add(encodingElement);
// ++ Setting https transport binding ++
var httpsElement = new HttpsTransportBindingElement();
// Messagge buffer size
httpsElement.MaxBufferSize = 50000000;
httpsElement.MaxReceivedMessageSize = 50000000;
httpsElement.MaxBufferPoolSize = 50000000;
httpsElement.RequireClientCertificate = true;
// Others
httpsElement.UseDefaultWebProxy = true;
binding.Elements.Add(httpsElement);
return binding;
}
And Service Sertificate set as
client.ClientCredentials.ClientCertificate.Certificate=cert;// From pfx file
client.ClientCredentials.ServiceCertificate.DefaultCertificate =serverCert;//from server certificate
I try to sign with my company smart card which is ACS38 smart card. If I use DefaultAlgotihmSuite Basic128 or Basic128Rsa15 then smartCard certificate succesfully sign body elements. I change algorihmsuite Basic256Sha256Rsa15 for requirement then I get KeySet does not exist. In this Smart Card have private key but WCF does not reach that private key.
Is there way to sign to Sign Soap Body with Sha256Rsa on SmartCard ?

The 'Action', 'http://www.w3.org/2005/08/addressing' required message part was not signed

I am accessing an external java-based web service I have no control over from a WCF client, using dual certificates for encryption and signature as well as custom binding. I am getting a successful response from the server but WCF is throwing a MessageSecurityException : The 'Action', 'http://www.w3.org/2005/08/addressing' required message part was not signed.
My custom binding:
private CustomBinding GetCustomBinding()
{
CustomBinding binding = new CustomBinding();
binding.OpenTimeout = new TimeSpan(0, 0, 20);
binding.CloseTimeout = new TimeSpan(0, 0, 20);
binding.SendTimeout = new TimeSpan(0, 5, 0);
binding.ReceiveTimeout = new TimeSpan(0, 5, 0);
var userNameToken = new UserNameSecurityTokenParameters();
userNameToken.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
var securityElement = new AsymmetricSecurityBindingElement();
securityElement.EnableUnsecuredResponse = true;
securityElement.IncludeTimestamp = true;
securityElement.RecipientTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.Never);
securityElement.InitiatorTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.AlwaysToRecipient);
securityElement.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic128Rsa15;
securityElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
securityElement.SetKeyDerivation(false);
securityElement.EndpointSupportingTokenParameters.Signed.Add(userNameToken);
securityElement.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
binding.Elements.Add(securityElement);
var encodingElement = new TextMessageEncodingBindingElement();
encodingElement.MessageVersion = MessageVersion.Soap11WSAddressing10;
encodingElement.WriteEncoding = Encoding.UTF8;
encodingElement.ReaderQuotas.MaxArrayLength = 50000000;
encodingElement.ReaderQuotas.MaxStringContentLength = 50000000;
binding.Elements.Add(encodingElement);
var httpsElement = new HttpsTransportBindingElement();
httpsElement.MaxBufferSize = 50000000;
httpsElement.MaxReceivedMessageSize = 50000000;
httpsElement.MaxBufferPoolSize = 50000000;
httpsElement.UseDefaultWebProxy = true;
binding.Elements.Add(httpsElement);
return binding;
}
Now I don't care if that Action element is signed or not, or even if it's not there at all, but hacking the response to remove the tag altogether results in a 'No signature message parts were specified for messages with the '' action.' exception.
How can I configure my client to accept the Action and other addressing elements in the response message as they are? Alternatively, what can I change them to so WCF will let them pass?
To override the default checking of the remote Secure Sockets Layer (SSL) certificate used for authentication, specify this on client:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
To investigate the certificate errors, check the sslPolicyErrors parameter of the RemoteCertificateValidationCallback delegate (Link to MSDN manual page).

Creating Headers (wsse) Section of WCF Client Programmatically in C#

how do make a the following section of Service Settings of app.config in C# programmatically:
<client>
<endpoint address="https://someServiceUrl"
binding="basicHttpBinding" bindingConfiguration="Contact"
contract="ServiceReference.PostingWebService" name="PostingWebServicePort">
<headers>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>someusername</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>somepassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
</client>
I have managed to generate binding section (not included above) and endpoint section from C#. I am unable to create the headers section.
The error that comes up is: (this is because I don't have headers section when I generate everything from C#)
This service requires <wsse:Security>, which is missing.
the headers section is important, as if I exclude it from the config and run the code using config it also gives the above error.
I don't want to use web.config/app.config. I have to run every thing from C#. (the above app.config works fine, but I want to do that same through C#)
NOTE: THE UPDATES BELOW ARE BASED ON THE SOLUTION PROVIDED BELOW PLEASE GO THROUGH THE COMMENTS ON THE SOLUTION BELOW, FOR BETTER UNDERSTANDING
UPDATE 1: (programmatically using BasicHttpBinding first)
BasicHttpBinding binding = new BasicHttpBinding();
binding.Name = "Contact";
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.SendTimeout = TimeSpan.FromMinutes(1);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferSize = 524288;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 524288;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 65536;
binding.ReaderQuotas.MaxArrayLength = 131072;
binding.ReaderQuotas.MaxBytesPerRead = 32768;
binding.ReaderQuotas.MaxNameTableCharCount = 131072;
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
binding.Security.Transport.Realm = "";
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
CustomBinding customBinding = new CustomBinding(binding);
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
// Remove security timestamp because it is not used by your original binding
//element.IncludeTimestamp = false; (element is NULL in my case)
EndpointAddress endpoint = new EndpointAddress("https://myserviceaddress");
PostingWebServiceClient client = new PostingWebServiceClient(customBinding, endpoint);
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
client.getActiveChannels(new getActiveChannels());
Using Custom Bindgin Directly:
SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
TextMessageEncodingBindingElement encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
HttpsTransportBindingElement transportElement = new HttpsTransportBindingElement();
CustomBinding customBinding = new CustomBinding(securityElement, encodingElement, transportElement);
EndpointAddress endpoint = new EndpointAddress("https://myserviceaddress");
PostingWebServiceClient client = new PostingWebServiceClient(customBinding, endpoint);
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
client.getActiveChannels(new getActiveChannels());
You don't have to configure header directly in this case because your scenario should be supported by BasicHttpBinding or CustomBinding directly.
If you need to configure it from C# you must create binding in code:
// Helper binding to have transport security with user name token
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
// Rest of your binding configuration comes here
// Custom binding to have access to more configuration details of basic binding
CustomBinding customBinding = new CustomBinding(binding);
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
// Remove security timestamp because it is not used by your original binding
element.IncludeTimestamp = false;
EndpointAddress address = new EndpointAddress("https://...");
ProxyWebServiceClient client = new ProxyWebServiceClient(customBinding, address);
client.ClientCredentials.UserName.UserName = "...";
client.ClientCredentials.UserName.Password = "...";
Other solution is building custom binding directly instead of starting with basic binding:
SecurityBindingElemetn securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
TextMessageEncodingBindingElement encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
HttpsTransportBindingElement tranportElement = new HttpsTransportBindingElement();
// Other configurations of basic binding are divided into properties of
// encoding and transport elements
CustomBinding customBinding = new CustomBinding(securityElement, encodingElement, transportElement);
EndpointAddress address = new EndpointAddress("https://...");
ProxyWebServiceClient client = new ProxyWebServiceClient(customBinding, address);
client.ClientCredentials.UserName.UserName = "...";
client.ClientCredentials.UserName.Password = "...";
Look at the accepted answer to this StackOverflow question. It shows how to programatically add client credentials to the proxy. It also shows adding the headers in the client endpoint configuration XML which I hadn't seen before.

WCF SSL certificate using an enterprise CA

For an application, I need to have a SSL certificate for a WCF service,
So we installed it. If I go with an internet browser with a web browser trough https, I've got no problem, no warning, nothing, so I suppose that this certificate is considered as valid for windows.
The problem is that when I'm trying to connect to my WCF server, I got this error:
The X.509 certificate CN=myHostName, OU=tom, O=myDomainName,
L=MyLocation, S=SO, C=CH chain building failed. The certificate that
was used has a trust chain that cannot be verified. Replace the
certificate or change the certificateValidationMode. The revocation
function was unable to check revocation because the revocation server
was offline.
What can be wrong? How can I know which part of the chain is unvalid? Is there any way to know what is the missing part?
Here is my code
The server:
ServiceHost myHost = new ServiceHost(typeof(MyService));
WSHttpBinding binding = new WSHttpBinding
{
ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue, MaxBytesPerRead = int.MaxValue, MaxNameTableCharCount = int.MaxValue },
MaxReceivedMessageSize = int.MaxValue
};
TimeSpan timeoutSpan = TimeSpan.FromMilliseconds(timeout);
binding.CloseTimeout = timeoutSpan;
binding.OpenTimeout = timeoutSpan;
binding.ReceiveTimeout = timeoutSpan;
binding.SendTimeout = timeoutSpan;
binding.ReliableSession.InactivityTimeout = timeoutSpan;
binding.MaxBufferPoolSize = int.MaxValue;
//we set the security type
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
//we set the server's certificate
myHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, ConfigurationManager.AppSettings["Hostname"]);
myHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
//we add the endPoint(and we indicate which methods are exposed through the interface
myHost.AddServiceEndpoint(services[port], binding, String.Format("http://localhost:{0}", port));
//Some services doesn't need an authentication
if (!servicesWithoutAuth.Contains(services[port]))
{
//We set the authentifier:
myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
myHost.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
//we set the AuthorizationPolicy
List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy> { new CustomAuthorizationPolicy() };
myHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();
}
else
{
//We set the authentifier:
myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new NoUserNamePasswordValidator();
}
//We bypass the certificate verification(our certificate is only self signed)
//HACK Only to desactivate the SSL check:
ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate;
//HACK: Remove when debug finished
private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
return true;
}
My client side:
// the remote adress is of the form "net.tcp://localhost:8000"
string remoteAddress = String.Format("{0}://{1}:{2}", Tools.GetDescription(accessInfo.ServiceHost.Protocol), accessInfo.ServiceHost.HostName, accessInfo.PortNumber);
// HACK: binding depends on protocol -> switch over accessInfo.ServiceHost.Protocol
// avoid seralization/deserialization problems with large XML's
WSHttpBinding binding = new WSHttpBinding();
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.ReaderQuotas.MaxDepth = int.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
TimeSpan timeoutSpan = DateTime.Now.AddMinutes(30) - DateTime.Now;
binding.CloseTimeout = timeoutSpan;
binding.OpenTimeout = timeoutSpan;
binding.ReceiveTimeout = timeoutSpan;
binding.SendTimeout = timeoutSpan;
binding.ReliableSession.InactivityTimeout = timeoutSpan;
//++
binding.MaxBufferPoolSize = int.MaxValue;
//we set the security type
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
ChannelFactory<TService> channelFactory = new ChannelFactory<TService>(binding, remoteAddress);
channelFactory.Credentials.UserName.UserName = ((UsernamePasswordAuthentication)authInfos).Username;
channelFactory.Credentials.UserName.Password = ((UsernamePasswordAuthentication)authInfos).Password;
//We set the maxItemsInObjectGraph
foreach (OperationDescription op in channelFactory.Endpoint.Contract.Operations)
{
DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
}
SamlSecurityTokenAuthenticator authenticator = new SamlSecurityTokenAuthenticator(new List<SecurityTokenAuthenticator>(new SecurityTokenAuthenticator[] { new RsaSecurityTokenAuthenticator(), new X509SecurityTokenAuthenticator(X509CertificateValidator.None) }), TimeSpan.FromDays(5));
_service = channelFactory.CreateChannel();
How can I know which part of the chain is unvalid? Is there any way to
know what is the missing part?
Well, from my experience, if you open your keystore and view it, you should see that your certificate clearly forms a chain. I don't know what tool you use to view your keystore (or if your using the windows keystore), but when you view your key, you should see a chain of some kind. If a chain is formed correctly, it will appear correctly, and doesn't have any missing parts.
My guess is that when you imported your certificate reply, it didn't form the chain for some reason. In other words, your certificate is in your keystore as a "unchained" public key.

Modify endpoint ReaderQuotas programmatically

I have a dynamic client to a service. How can i change the ReaderQuotas property of it's endpoint binding?
I tried like this but it doesn't work ...
DynamicProxyFactory factory = new DynamicProxyFactory(m_serviceWsdlUri);
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
Binding binding = endpoint.Binding;
binding.GetProperty<XmlDictionaryReaderQuotas>(new BindingParameterCollection()).MaxArrayLength = 2147483647
binding.GetProperty<XmlDictionaryReaderQuotas>(new BindingParameterCollection()).MaxBytesPerRead =2147483647;
binding.GetProperty<XmlDictionaryReaderQuotas>(new BindingParameterCollection()).MaxDepth = 2147483647;
binding.GetProperty<XmlDictionaryReaderQuotas>(new BindingParameterCollection()).MaxNameTableCharCount = 2147483647;
binding.GetProperty<XmlDictionaryReaderQuotas>(new BindingParameterCollection()).MaxStringContentLength = 2147483647;
}
Even after doing this the ReaderQuotas values remain the default ones.
I also tried like this and still doesn't work:
DynamicProxyFactory factory = new DynamicProxyFactory(m_serviceWsdlUri);
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
System.ServiceModel.Channels.BindingElementCollection bec = endpoint.Binding.CreateBindingElements();
System.ServiceModel.Channels.TransportBindingElement tbe = bec.Find<System.ServiceModel.Channels.TransportBindingElement>();
tbe.MaxReceivedMessageSize = 2147483647;
tbe.MaxBufferPoolSize = 2147483647;
TextMessageEncodingBindingElement textBE = bec.Find<TextMessageEncodingBindingElement>();
if (textBE != null)
{
textBE.ReaderQuotas.MaxStringContentLength = 2147483647;
textBE.ReaderQuotas.MaxArrayLength = 2147483647;
textBE.ReaderQuotas.MaxBytesPerRead = 2147483647;
textBE.ReaderQuotas.MaxDepth = 2147483647;
textBE.ReaderQuotas.MaxNameTableCharCount = 2147483647;
}
}
I need this so I can send more than 8kb to the service.
Setting quotas on a BindingElement after the binding is created has no effect on that binding.
Edit (since you don't know what binding is used):
You can use reflection to set the property. Note you should make sure the Binding actually has the property before setting it. Not all bindings have this property. If you try to set it on a binding that doesn't support it, the example will throw an exception.
Binding binding = endpoint.Binding;
XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = _sanebutusablelimit_;
myReaderQuotas.MaxArrayLength = _sanebutusablelimit_;
myReaderQuotas.MaxBytesPerRead = _sanebutusablelimit_;
myReaderQuotas.MaxDepth = _sanebutusablelimit_;
myReaderQuotas.MaxNameTableCharCount = _sanebutusablelimit_;
binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
Hope this helps you a bit.
Why are you solving that in a such complex way, just alter the ReaderQuotas directly:
ie:
WSHttpBinding WebBinding = new WSHttpBinding();
WebBinding.ReaderQuotas.MaxArrayLength = int.MaxValue;
WebBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
WebBinding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
This will work without that weird reflection sample.
Cheers
Also to be noted, is that the following properties of the Binding also need to be updated for the complete solution:
binding2.MaxBufferSize = 2147483647;
binding2.MaxReceivedMessageSize = 2147483647;
For the benefit of others here is a sample that programmatically sets the ReaderQuotas on both the client and the server along with the 2 properties above:
Client code:
WebHttpBinding binding2 = new WebHttpBinding();
XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 2147483647;
myReaderQuotas.MaxArrayLength = 2147483647;
myReaderQuotas.MaxBytesPerRead = 2147483647;
myReaderQuotas.MaxDepth = 2147483647;
myReaderQuotas.MaxNameTableCharCount = 2147483647;
binding2.GetType().GetProperty("ReaderQuotas").SetValue(binding2, myReaderQuotas, null);
binding2.MaxBufferSize = 2147483647;
binding2.MaxReceivedMessageSize = 2147483647;
ServiceEndpoint ep = new ServiceEndpoint(ContractDescription.GetContract(typeof(IMyService)),
binding2, new EndpointAddress("http://localhost:9000/MyService"));
WebChannelFactory<IMyService> cf2 = new WebChannelFactory<IMyService>(ep);
IMyService serv = cf2.CreateChannel();
serv.PrintNameDesc("Ram", new string('a', 100*1024*1024));
Server code:
WebHttpBinding binding2 = new WebHttpBinding();
XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 2147483647;
myReaderQuotas.MaxArrayLength = 2147483647;
myReaderQuotas.MaxBytesPerRead = 2147483647;
myReaderQuotas.MaxDepth = 2147483647;
myReaderQuotas.MaxNameTableCharCount = 2147483647;
binding2.GetType().GetProperty("ReaderQuotas").SetValue(binding2, myReaderQuotas, null);
binding2.MaxBufferSize = 2147483647;
binding2.MaxReceivedMessageSize = 2147483647;
WebServiceHost host2 = new WebServiceHost(typeof(MyService));
host2.AddServiceEndpoint(typeof(IMyService), binding2, new Uri("http://localhost:9000/MyService"));
host2.Open();
Where the contract is:
[ServiceContract]
public interface IMyService
{
[WebInvoke(Method = "PUT",
UriTemplate = "My/{name}/",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
RequestFormat = WebMessageFormat.Xml)]
[OperationContract]
void PrintNameDesc(string name, string desc);
}

Categories