Increase MaxItemsInObjectGraph for WCF Service client - c#

I am referencing a WCF service from a C# dll so the app.config file generated is not being read. I am manually trying to create a service client via the code below; however, I am getting errors that I need to increase the MaxItemsInObjectGraph. The service that is running is already set to int.MaxValue so I just need to increase it in the TestServiceClient now. Any ideas?? Thanks in advance!
var client = new TestServiceClient(GetBinding(), GetEndpointAddress());
private static EndpointAddress GetEndpointAddress()
{
var endpoint = new EndpointAddress("https://localhost:8000/ServiceModel/service");
return endpoint;
}
private static Binding GetBinding()
{
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{
MessageEncoding = WSMessageEncoding.Text,
TextEncoding = Encoding.UTF8,
BypassProxyOnLocal = false,
UseDefaultWebProxy = true,
CloseTimeout = new TimeSpan(10, 0, 0),
OpenTimeout = new TimeSpan(10, 0, 0),
SendTimeout = new TimeSpan(10, 0, 0),
ReceiveTimeout = new TimeSpan(10, 0, 0),
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferPoolSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue,
AllowCookies = false,
TransferMode = TransferMode.StreamedResponse,
ReaderQuotas =
{
MaxDepth = 32,
MaxStringContentLength = Int32.MaxValue,
MaxArrayLength = 6553600,
MaxBytesPerRead = 4096,
MaxNameTableCharCount = 16384
}
};
return basicHttpBinding;
}
Below is my solution:
private static ITestServiceClient GetClient()
{
var factory = new ChannelFactory<ITestServiceClient >(GetBinding(), GetEndpointAddress());
foreach (var dataContractBehavior in factory.Endpoint.Contract.Operations
.Select(operation => operation.Behaviors.Find<DataContractSerializerOperationBehavior>())
.Where(dataContractBehavior => dataContractBehavior != null))
{
dataContractBehavior.MaxItemsInObjectGraph = Int32.MaxValue;
}
var client = factory.CreateChannel();
return client;
}

Try in client.Endpoint.Contract.Operations
foreach (var operation in operations)
{
var dataContractBehavior = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = value;
}
}

Related

Set the MaxClockSkew when using NetTcpBinding with TransportWithMessageCredential

I'm using WCF with the NetTcpBinding and I'm unable to set the MaxClockSkew as the SymmetricSecurityBindingElement is null when using SecurityMode of TransportWithMessageCrediential. Does anyone know how this is done when using TransportWithMessageCrediential SecurityMode?
private Binding GetNetTcpBinding()
{
long MaxReceivedMessageSize = 2147483647;
int MaxStringContentLength = 2147483647;
int MaxBytesPerRead = 2147483647;
int MaxNameTableCharCount = 100000;
var timeout = 5;
var maxClockSkew = new TimeSpan(0, 30, 0);
var binding = new NetTcpBinding
{
OpenTimeout = new TimeSpan(0, 0, timeout),
SendTimeout = new TimeSpan(0, 0, timeout),
ReceiveTimeout = new TimeSpan(0, 0, timeout),
MaxReceivedMessageSize = MaxReceivedMessageSize,
ReaderQuotas = new XmlDictionaryReaderQuotas
{
MaxArrayLength = MaxBytesPerRead,
MaxBytesPerRead = MaxBytesPerRead,
MaxNameTableCharCount = MaxNameTableCharCount,
MaxStringContentLength = MaxStringContentLength,
MaxDepth = MaxBytesPerRead
}
};
binding.ReliableSession = new OptionalReliableSession
{
Enabled = true,
InactivityTimeout = new TimeSpan(0, 0, timeout),
Ordered = true
};
binding.Security = new NetTcpSecurity
{
Mode = SecurityMode.TransportWithMessageCredential,
Message = new MessageSecurityOverTcp
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256
},
Transport = new TcpTransportSecurity
{
ClientCredentialType = TcpClientCredentialType.Certificate,
SslProtocols = SslProtocols.Tls12
}
};
var customBinding = new CustomBinding(binding);
var security =
customBinding.Elements.Find<SymmetricSecurityBindingElement>();
// NOTE: This Always Returns NULL
if (security != null)
{
security.LocalClientSettings.MaxClockSkew = maxClockSkew;
security.LocalServiceSettings.MaxClockSkew = maxClockSkew;
// Get the System.ServiceModel.Security.Tokens.SecureConversationSecurityTokenParameters
var secureTokenParams =
(SecureConversationSecurityTokenParameters)security.ProtectionTokenParameters;
// From the collection, get the bootstrap element.
var bootstrap = secureTokenParams.BootstrapSecurityBindingElement;
// Set the MaxClockSkew on the bootstrap element.
bootstrap.LocalClientSettings.MaxClockSkew = maxClockSkew;
bootstrap.LocalServiceSettings.MaxClockSkew = maxClockSkew;
return customBinding;
}
return binding;
}
I'm unable to find any solutions for this and the documentation seems to be out of date. This only works if you use SecurityMode.Message.

WCF service run very slow with reliable session

The server is hosted on a WPF application and use net.tcp binding for duplex channel. We have the client (.NET 4.0) to send a burst of async request to the server. After reliable session is on, the service become really slow (approx. 50-100 call/s) and callback messages aren't sent to the client.
The issue happens in two cases.
We send approx. 1000 messages per seconds to the server. If we send 300-500 messages is all OK.
We send a single message to the server with size 10-20 MB. And in this case messages from the server callbacks wait until the big message is sending.
Below are the codes for the server and client.
Server's binding:
(Also we tried to use standart net.tcp binding istead of custom one but it didn't help)
var customBinding= new CustomBinding()
{
CloseTimeout = new TimeSpan(0, 1, 10),
OpenTimeout = new TimeSpan(0, 1, 10),
ReceiveTimeout = new TimeSpan(0, 5, 30),
SendTimeout = new TimeSpan(0, 2, 0)
};
customBinding.Elements.Add(new BinaryMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Default,
ReaderQuotas =
{
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxArrayLength = int.MaxValue
}
});
customBinding.Elements.Add(new ReliableSessionBindingElement()
{
AcknowledgementInterval = TimeSpan.FromMilliseconds(1),
FlowControlEnabled = true,
InactivityTimeout = new TimeSpan(0, 30, 0),
MaxPendingChannels = 1000,
MaxRetryCount = 10,
MaxTransferWindowSize = 4096,
Ordered = true,
ReliableMessagingVersion = ReliableMessagingVersion.Default
});
var tcpTransport = new TcpTransportBindingElement()
{
ChannelInitializationTimeout = TimeSpan.FromSeconds(30),
ConnectionBufferSize =8192,
ListenBacklog = 10000000,
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
MaxOutputDelay= TimeSpan.FromMilliseconds(1000),
MaxPendingAccepts = int.MaxValue,
MaxPendingConnections = 40000,
MaxReceivedMessageSize = int.MaxValue,
PortSharingEnabled = true,
TransferMode = TransferMode.Buffered,
};
tcpTransport.ConnectionPoolSettings.GroupName = "OnlineList";
tcpTransport.ConnectionPoolSettings.IdleTimeout = TimeSpan.FromMinutes(5);
tcpTransport.ConnectionPoolSettings.LeaseTimeout = TimeSpan.FromMinutes(5);
tcpTransport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = 40000;
customBinding.Elements.Add(tcpTransport);
Client side configuration:
BaseTimeout = 7000;
int.MaxValue = 2147483647;
///Common
CloseTimeout = new TimeSpan(0, 0, BaseTimeout),
OpenTimeout = new TimeSpan(0, 0, BaseTimeout),
ReceiveTimeout = new TimeSpan(0, 0, BaseTimeout*4),
SendTimeout = new TimeSpan(0, 0, BaseTimeout),
///Security
Security = { Mode = SecurityMode.None },
///Session
ReliableSession =
{
Enabled = true,
InactivityTimeout = new TimeSpan(1, 10, 0),
Ordered = true
},
///Buffer and message
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
///ReaderQuotas
ReaderQuotas =
{
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxArrayLength = int.MaxValue
},
//Other
PortSharingEnabled = true,
MaxConnections = 1000,
TransactionFlow = true,
TransferMode = TransferMode.Buffered,

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).

Tridion 2011 Core Service: Unable to connect in a SSO environment

While trying to connect to the Core Service I get the following error:
The HTTP request was forbidden with client authentication scheme 'Anonymous'
The Tridion environment is configured with SSO from SiteMinder.
Here's my code:
public static ICoreService2010 GetTridionClient()
{
var binding = new BasicHttpBinding()
{
Name = "BasicHttpBinding_TridionCoreService",
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 10, 0),
SendTimeout = new TimeSpan(0, 1, 0),
AllowCookies = false,
BypassProxyOnLocal = false,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferSize = 4194304, // 4MB
MaxBufferPoolSize = 4194304,
MaxReceivedMessageSize = 4194304,
MessageEncoding = WSMessageEncoding.Text,
TextEncoding = System.Text.Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxDepth = 32,
MaxStringContentLength = 4194304, // 4MB
MaxArrayLength = 4194304,
MaxBytesPerRead = 4194304,
MaxNameTableCharCount = 16384
},
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.None,
},
Message = new BasicHttpMessageSecurity()
{
ClientCredentialType = BasicHttpMessageCredentialType.UserName
}
}
};
string hostname = ConfigurationManager.AppSettings["TridionUrl"];
string username = ConfigurationManager.AppSettings["TridionUsername"];
hostname = string.Format("{0}{1}{2}",
hostname.StartsWith("http") ? "" : "http://",
hostname,
hostname.EndsWith("/") ? "" : "/");
var endpoint = new EndpointAddress(hostname +
"/webservices/CoreService.svc/basicHttp_2010");
var factory = new ChannelFactory<ICoreService2010>(binding, endpoint);
factory.Credentials.UserName.UserName = username;
return factory.CreateChannel();
}
Does anybody have experience of interacting with the Core Service with an authentication type other than Windows?
UPDATE:
I now get the error:
The HTTP request was forbidden with client authentication scheme 'Basic'.
What clientCredentialType should be used in the /webservices/web.config for the bindings?
When I uncomment the SsoAgentHttpModule in the /webservies/web.config we get a 500 error on the webservice, so SDL told us to leave this commented out.
I take it that this module is required for the CoreService to authenticate with authentication scheme 'Basic'?
There are 2 problems with your code:
You have set authentiction to anonymous on the server and assumed that same should be set on the client, but it's not the case. You have also enabled LDAP SSO module on the server that kicks in as soon as you turn the anonymous authentication on. On the client side it will look like plain basic authentication, so you client security code should be like this:
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.Basic,
}
}
You have set username, but not password, so:
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
Also, keep in mind that you might need to specify User Name Qualifier (SSO by default) when setting user, like SSO\user
This should move you a step closer, if you will still have problems - please update your question with recent exception.

Categories