How to programatically create a Custom Binding with TransportWithMessageCredential? - wcf

I need to programatically create a wsHttpBinding (Custom Binding) and for this I need the following configuration:
<binding name="ws_IMembershipService_TransportWithMessageCredential_Username" messageEncoding="Text" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="true" maxBufferPoolSize="524288" maxReceivedMessageSize="10000000">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" />
</security>
</binding>
What is the equivalent to this config in C#?

Should be something like this:
EDIT: Still not sure if this will get you what you need, but maybe a good starting point. If not let me know I will delete.
CustomBinding cb = new CustomBinding()
{
SendTimeout = System.TimeSpan.FromMinutes(1),
ReceiveTimeout = System.TimeSpan.FromMinutes(1),
CloseTimeout = System.TimeSpan.FromMinutes(1),
OpenTimeout = System.TimeSpan.FromMinutes(1),
};
HttpsTransportBindingElement a = new HttpsTransportBindingElement();
a.MaxReceivedMessageSize = 10000000;
a.MaxBufferSize = 524288;
a.BypassProxyOnLocal = true;
a.AuthenticationScheme = AuthenticationSchemes.None;
SymmetricSecurityBindingElement b = SecurityBindingElement.CreateSspiNegotiationBindingElement(true);
TextMessageEncodingBindingElement c = new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8);
SecurityBindingElement d = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
d.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
c.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() { MaxDepth = 32, MaxStringContentLength = 8192, MaxArrayLength = 16384, MaxBytesPerRead = 4096, MaxNameTableCharCount = 16384 };
cb.CreateBindingElements();
cb.Elements.Add(a);
cb.Elements.Add(b);
cb.Elements.Add(c);
cb.Elements.Add(d);

Related

Transport level security in an intranet Silverlight 5 application

I am implementing transport level security in an intranet Silverlight 5 application.
Binding used is custom netTcpBinding and on server end I have enabled security with below settings and PrincipalPermission.
<customBinding>
<binding closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="02:00:00" sendTimeout="00:05:00">
<binaryMessageEncoding maxSessionSize="1000000">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="16384" maxNameTableCharCount="16384" />
</binaryMessageEncoding>
<windowsStreamSecurity protectionLevel="EncryptAndSign"/>
<tcpTransport portSharingEnabled="false" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
When my client is a normal c# console app and proxy created using channel fatory everything works fine.
var tcpBinding = new CustomBinding();
tcpBinding.Elements.Add(new BinaryMessageEncodingBindingElement());
var windowsStreamSecurityBindingElement=new WindowsStreamSecurityBindingElement();
windowsStreamSecurityBindingElement.ProtectionLevel= System.Net.Security.ProtectionLevel.EncryptAndSign;
tcpBinding.Elements.Add(windowsStreamSecurityBindingElement);
tcpBinding.Elements.Add(new TcpTransportBindingElement { MaxReceivedMessageSize = int.MaxValue, MaxBufferSize = int.MaxValue });
tcpBinding.ReceiveTimeout = new TimeSpan(6, 0, 0);
tcpBinding.SendTimeout = new TimeSpan(0, 30, 0);
tcpBinding.ReceiveTimeout = TimeSpan.FromDays(1);
var proxy = new ChannelFactoryServiceWrapper<IHello>(#"net.tcp://XYZ.globaltest.ABC.com:5580/Hello/tcp", tcpBinding).Channel;
var ping = proxy.Ping();
On client(Silverlight 5) I am using same above piece of code but it’s giving compile time error since WindowsStreamSecurityBindingElement is not available in Silverlight 5.
Please tell me any alternative for this.

How to use c# code to add bindingConfiguration attribute (WCF)

I have an endpoint in the app.config:
<endpoint address=""
binding="netTcpBinding"
bindingConfiguration="financeBinding"
name="RoutingServiceEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
The bindingConfiguration in app.config
<bindings>
<netTcpBinding>
<binding name="financeBinding" closeTimeout="00:10:10" openTimeout="00:10:10" sendTimeout="00:10:10" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
<!--transactionFlow="true"-->
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
Question is: how could i config this in the code? I need read the config for the database and bind it.
:)
With this you can configure your settings in the code:
using System.ServiceModel;
EndpointAddress endpoint = new EndpointAddress("http://yourAdress.svc");
NetTcpBinding binding = new NetTcpBinding();
binding.Name = "financeBinding";
binding.MaxBufferPoolSize = 2147483647;
binding.ReaderQuotas.MaxDepth = 2147483647;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
binding.ReaderQuotas.MaxBytesPerRead = 2147483647;
binding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
binding.OpenTimeout = new TimeSpan(0, 10, 10);
binding.CloseTimeout = new TimeSpan(0, 10, 10);
binding.SendTimeout = new TimeSpan(0, 10, 10);
binding.Security.Mode = SecurityMode.None;
yourClient client = new yourClient(binding, endpoint);

Programmatically adding an endpoint

I have a WCF service that I am connecting in client application. I am using following in configuration file.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyNameSpace.TestService" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:9100/TestService" binding="basicHttpBinding"
bindingConfiguration="MyNameSpace.TestService" contract="TestService.IService" name="MyNameSpace.TestService" />
</client>
</system.serviceModel>
In the code, I am calling API on this service as follows,
TestServiceClient client = new TestServiceClient()
client.BlahBlah()
Now I want to defined endpoint porgramatically. How can that be done? I commented out section from config file as I was thinking I will have to put some code on TestServiceClient instance to add endpoint dynamically but then it throws following exception at the point where TestServiceClient is instantiated.
Could not find default endpoint element that references contract
'TestService.IService' in the ServiceModel client configuration
section. This might be because no configuration file was found for
your application, or because no endpoint element matching this
contract could be found in the client element.
How can I accomplish this? Also any point on code examples for adding endpoint programmatically will be appreciated.
To create endpoints and bindings programmatically, you could do this on the service:
ServiceHost _host = new ServiceHost(typeof(TestService), null);
var _basicHttpBinding = new System.ServiceModel.basicHttpBinding();
//Modify your bindings settings if you wish, for example timeout values
_basicHttpBinding.OpenTimeout = new TimeSpan(4, 0, 0);
_basicHttpBinding.CloseTimeout = new TimeSpan(4, 0, 0);
_host.AddServiceEndpoint(_basicHttpBinding, "http://192.168.1.51/TestService.svc");
_host.Open();
You could also define multiple endpoints in your service config, and choose which one to connect to dynamically at run time.
On the client program you would then do this:
basicHttpBinding _binding = new basicHttpBinding();
EndpointAddress _endpoint = new EndpointAddress(new Uri("http://192.168.1.51/TestService.svc"));
TestServiceClient _client = new TestServiceClient(_binding, _endpoint);
_client.BlahBlah();
Can you just use:
TestServiceClient client = new TestServiceClient();
client.Endpoint.Address = new EndPointAddress("http://someurl");
client.BlahBlah();
Note that your binding configuration will no longer apply, as you're not using that endpoint configuration in your configuration file. You'll have to override that, too.
You can try:
TestServiceClient client = new TestServiceClient("MyNameSpace.TestService")
client.BlahBlah()
if not recheck namespace in file TestService is correct?

The maximum message size quota for incoming messages (65536) has been exceeded

I get this exception while creating scope for few tables all those tables are huge in design
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_ISyncServices" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows"
proxyCredentialType="None" realm="">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
<message clientCredentialType="Windows"
negotiateServiceCredential="true" algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
I have made MaxReceivedMessageSize to 2147483647
but still it is giving me below exception at this line
client.GetTableDescription(scopeName, syncTable)
The maximum message size quota for incoming messages (65536) has been exceeded.
To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
As per this question's answer
You will want something like this:
<bindings>
<basicHttpBinding>
<binding name="basicHttp" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
</binding>
</basicHttpBinding> </bindings>
Please also read comments to the accepted answer there, those contain valuable input.
If you are using CustomBinding then you would rather need to make changes in httptransport element.
Set it as
<customBinding>
<binding ...>
...
<httpsTransport maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
Updating the config didn't work for me, but I was able to edit the binding programmatically:
private YourAPIClient GetClient()
{
Uri baseAddress = new Uri(APIURL);
var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = 20000000;
binding.MaxBufferSize = 20000000;
binding.MaxBufferPoolSize = 20000000;
binding.AllowCookies = true;
var readerQuotas = new XmlDictionaryReaderQuotas();
readerQuotas.MaxArrayLength = 20000000;
readerQuotas.MaxStringContentLength = 20000000;
readerQuotas.MaxDepth = 32;
binding.ReaderQuotas = readerQuotas;
if (baseAddress.Scheme.ToLower() == "https")
binding.Security.Mode = BasicHttpSecurityMode.Transport;
var client = new YourAPIClient(binding, new EndpointAddress(baseAddress));
return client;
}
You need to make the changes in the binding configuration (in the app.config file) on the SERVER and the CLIENT, or it will not take effect.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647 " max...=... />
</basicHttpBinding>
</bindings>
</system.serviceModel>
You also need to increase maxBufferSize. Also note that you might need to increase the readerQuotas.
This worked for me:
Dim binding As New WebHttpBinding(WebHttpSecurityMode.Transport)
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
binding.MaxBufferSize = Integer.MaxValue
binding.MaxReceivedMessageSize = Integer.MaxValue
binding.MaxBufferPoolSize = Integer.MaxValue
For me, the settings in web.config / app.config were ignored. I ended up creating my binding manually, which solved the issue for me:
var httpBinding = new BasicHttpBinding()
{
MaxBufferPoolSize = Int32.MaxValue,
MaxBufferSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue,
ReaderQuotas = new XmlDictionaryReaderQuotas()
{
MaxArrayLength = 200000000,
MaxDepth = 32,
MaxStringContentLength = 200000000
}
};
My solution was to use the "-OutBuffer 2147483647" parameter in my query, which is part of the Common Parameters.
PS C:> Get-Help about_CommonParameters -Full

WCF TransportCredentialOnly not sending username and password

I have the following WCF client configuration:
<basicHttpBinding>
<binding name="basicHttpOCCWS" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="100000000" maxBufferPoolSize="524288"
maxReceivedMessageSize="100000000" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
In code, I am setting the username and password as follows:
client.ClientCredentials.UserName.UserName = _cacledUserId;
client.ClientCredentials.UserName.Password = _cachedPassword;
However, the web service running on Tomcat is returning an error:
"An authentication object was not found in the security context."
When I look at the HTTP header, it is missing credential information as shown below:
POST /occ600webservice/services/OCC_WS HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action=""
Host: 192.54.173.130:8080
Content-Length: 2223
Expect: 100-continue
Why are my credentials not being sent?
TIA.
Klaus
For others who run into the same problem, wrap each call to the secured web service resource like this:
var client = new WCClient();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] =
"Basic " +
Convert.ToBase64String(Encoding.ASCII.GetBytes(
client.ClientCredentials.UserName.UserName + ":" +
client.ClientCredentials.UserName.Password));
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] =
httpRequestProperty;
client.DoSomething();
}
see the following links:
Inserting headers 1
Inserting headers 2
Try changing the security element to also include the message element specifying the clientCredentialType to be UserName otherwise the transport doesn't know that you want to use the ClientCredentials.UserName object that you filled in.
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="None" />
<message clientCredentialType="UserName"/>
</security>