Programmatically define WCF Endpoints with Behaviours - c#

Can anyone show me how to programmatically create WSHttpBindings with Endpoint behaviours?
This is what was generated from WCF Add Service references to 6 WebServices which I manually editted to add behaviours so that all the endpoints uses the same behaviour .
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="epBehaviour">
<clientCredentials>
<clientCertificate findValue="This is my TEST Cert" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IQuote" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_ICommit" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IRetrieve" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IInfo" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IPurge" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_ISearch" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://my.service.com/WCFServices/Info.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInfo" contract="InfoWcfWS.IInfo" name="WSHttpBinding_IInfo" />
<endpoint address="https://my.service.com/WCFServices/Quote.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IQuote" contract="QuoteWcfWS.IQuote" name="WSHttpBinding_IQuote" />
<endpoint address="https://my.service.com/WCFServices/Commit.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommit" contract="CommitWcfWS.ICommit" name="WSHttpBinding_ICommit" />
<endpoint address="https://my.service.com/WCFServices/Retrieve.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IRetrieve" contract="RetrieveWcfWS.IRetrieve" name="WSHttpBinding_IRetrieve" />
<endpoint address="https://my.service.com/WCFServices/Purge.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IPurge" contract="PurgeWcfWS.IPurge" name="WSHttpBinding_IPurge" />
<endpoint address="https://my.service.com/WCFServices/Search.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISearch" contract="SearchWcfWS.ISearch" name="WSHttpBinding_ISearch" />
</client>
</system.serviceModel>
Currently with the generated Proxy from the "Add Service" and adding the behaviour "epBehaviour" which is referenced in the endpoints as a behaviourConfiguration, I can make calls to the endpoints.
Now, my next step is to define the behaviour part and the URL as configurations (May be in the of the web.config) so that I can have different config for Staging and Production.
So my sample Staging config will have the URL defined as below
<appSettings>
<add key="ServiceUrl.Tls12.Quote" value="https://my.service.com/WCFServices/Quote.svc" />
<add key="ServiceUrl.Tls12.Commit" value="https://my.service.com/WCFServices/Commit.svc" />
<add key="ServiceUrl.Tls12.Retrieve" value="https://my.service.com/WCFServices/Retrieve.svc" />
<add key="ServiceUrl.Tls12.Info" value="https://my.service.com/WCFServices/Info.svc" />
<add key="ServiceUrl.Tls12.Purge" value="https://my.service.com/WCFServices/Purge.svc" />
<add key="ServiceUrl.Tls12.Search" value="https://my.service.com/WCFServices/Search.svc" />
</appSettings>
So if I'm consuming the "Info" WebService, my code should be something like
//Code is missing how to define all the specifics like behaviours.
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
InfoWcfWS.InfoClient proxyNew = new InfoWcfWS.InfoClient(binding, endpoint);
In Summary, given the generated config after an "Add Service", to generate my Proxy Classes, I would like to remove all the config generated by VS and define my own config which will hold the URL; Everything else like endpoints URI, behaviours ..etc should be instantiated programmatically.
Thanks

You have to create instances of the behavior you need either from the System.ServiceModel.Description namespace or create them yourself and then add them to a ChannelFactory.
For your example you create a ChannelFactory for the interface you want and any binding you prefer. You then instantiate a ClientCredentials behavior, configure any of the settings you need on it and add it to the EndPointBehaviors of the ChannelFactory. Then you're ready to create a clientchannel that will give you an object that implements your service interface. You can use that similar as the generated client.
// binding
var binding = new WSHttpBinding();
// using System.ServiceModel
var channelFactory = new ChannelFactory<InfoWcfWS.IInfo>(binding);
// using System.ServiceModel.Description
var endpointClientbehavior = new ClientCredentials();
endpointClientbehavior.ClientCertificate
.SetCertificate(
"This is my TEST Cert",
StoreLocation.LocalMachine,
StoreName.My);
// add the behavior to the endpoint
channelFactory.Endpoint.EndpointBehaviors.Add(endpointClientbehavior);
// done configuring;
channelFactory.Open();
var endpoint = new EndpointAddress(
new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
// create the clientChannel
var client = channelFactory.CreateChannel(endpoint);
client.Open();
// client implements the operations on InfoWcfWS.IInfo

In the end, I found a simpler way of achieving this - This is one of the method Info I'm accessing:
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("https://my.service.com/WCFServices/Info.svc"));
binding.Name = "WSHttpBinding_IInfo";
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.Security = new WSHttpSecurity();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport = new HttpTransportSecurity();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message = new NonDualMessageSecurityOverHttp();
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.Security.Message.EstablishSecurityContext = false;
InfoClient proxy = new InfoClient(binding, endpoint);
proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "This is my TEST Cert");
object response = proxy.ServiceMethod();

Related

Set max time skew in wcf with net.tcp binding

I have a WCF service with net.tcp endpoints using custom usernamePassswordValidator, custom authorization and TransportWithMessageCredential with credential type "Username" (see below).
Server and client work fine - unless the time skew between server and client machine are more than 5 minutes.
Now I try to set the max skew time in code. I tried to adapt code snippets intended for WSHttpBindings from MSDN and used the custom binding on server and client:
binding = GetSecuredBindingFromServerOrClient();
CustomBinding myCustomBinding = new CustomBinding(binding);
var security = myCustomBinding.Elements.Find<TransportSecurityBindingElement>(); // TransportSecurityBindingElement or SecurityBindingElement
security.LocalClientSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.DetectReplays = false;
security.IncludeTimestamp = false;
// on client: use this custom binding in channel factory
var channelFactory = new ChannelFactory<ICheckerService>(customBinding, someAddress);
// on server: Update binding with customBinding
endpoint.Binding = myCustomBinding;
Still the connection fails with a MessageSecurityException when there is a time skew for more than 5 minutes (default value). I set also IncludeTimestamp to false or true but neither of them improved the situation.
The server behavior is:
<behavior name="customUserNamePasswordSecurityBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MySecurity.BasicAuthenticationValidator, MySecurity.Services"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Security.CustomAuthorizationPolicy, MySecurity.Services"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
Then endpoint bindings are:
<binding name="tcpUserNameAuthentication">
<reliableSession enabled="true"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
Did anybody get the time skew working based on the above configuration with TransportWithMessageCredential and net.tcp? Or is there a basic misunderstanding?
On my side, MaxClockSkew works well if I use NetTcp protocol, which requires a certificate on the server-side (need to add the management permission of the private key to the account running the service) and username/password on the client-side.
At first, I transform the Nettcpbinding to Custombinding.
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
Then I invocate the service with the client proxy class when I change the time on the client-side, it works well when the client time varies within 7minutes on the server-side. if I didn't set up the MaxClockSkew on the server-side. it only works within 5minutes the server-side time.
Please refer to the below example, wish it is useful to you.
Server-side(console application)
class Program
{
static void Main(string[] args)
{
using (ServiceHost sh=new ServiceHost(typeof(MyService)))
{
sh.Open();
Console.WriteLine("Service is ready....");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
interface IService
{
[OperationContract]
string GetData();
}
public class MyService : IService
{
public string GetData()
{
return DateTime.Now.ToString();
}
}
public class MyValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName != "jack" || password != "123456")
{
throw new Exception("My Error");
}
}
}
App.config
<system.serviceModel>
<services>
<service name="Server1.MyService" behaviorConfiguration="mybehavior">
<endpoint address="" binding="customBinding" contract="Server1.IService" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:800"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="5ba5022f527e32ac02548fc5afc558de1d314cb6" x509FindType="FindByThumbprint" storeLocation="LocalMachine" storeName="My"/>
<userNameAuthentication customUserNamePasswordValidatorType="Server1.MyValidator,Server1" userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client-side.
ServiceReference1.ServiceClient client = new ServiceClient();
client.ClientCredentials.UserName.UserName = "jack";
client.ClientCredentials.UserName.Password = "123456";
try
{
var result = client.GetData();
Console.WriteLine(result);
}
catch (Exception)
{
throw;
}
App.config(auto-generated)
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IService">
<security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false" canRenewSecurityContextToken="true">
<secureConversationBootstrap defaultAlgorithmSuite="Default"
authenticationMode="UserNameForCertificate" requireDerivedKeys="true"
includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false">
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</secureConversationBootstrap>
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</security>
<binaryMessageEncoding />
<tcpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="net.tcp://10.157.13.69:800/" binding="customBinding"
bindingConfiguration="CustomBinding_IService" contract="ServiceReference1.IService"
name="CustomBinding_IService">
<identity>
<certificate encodedValue="blablabla" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Feel free to let me know if there is anything I can help with.

C# ASMX Service throwing The content type text/html; charset=UTF-8 of the response message does not match the content type error

I have added a ASMX service reference to my project by doing right click on the root --> add service reference.
I have it like this on my web.config file:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="xxx" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="serviceaddress"
binding="basicHttpBinding" bindingConfiguration="xxx"
contract="xxx" name="xxx" />
</client>
</system.serviceModel>
This service has a method that receives a string with a username and validates if it exists.
The problem is that I'm testing it on Postman and it's returning the following error message:
The content type text/html; charset=UTF-8 of the response message does not match the content type
I've already checked on other posts similar like this one but I'm not able to find the solution.
Here's the method that I invoke which is throwing the error:
public static List<UserInformation> GetUsersByUserName(string userName)
{
try
{
var usersServiceClient = new LDapServicesSoapClient();
var requestMessage = new LDapUserNameLookupRequest();
requestMessage.UserName = userName;
requestMessage.AccessKey = "secretkey";
var response = usersServiceClient.LDapGetUserByUserName(requestMessage);
return response.Users.ToList();
}
catch (CommunicationException e)
{
if (e.InnerException is QuotaExceededException)
{
throw new Exception("We have found many users, please write another filter");
}
else
{
throw new Exception(e.Message, e);
}
}
}
Adding this configuration to my web.config file did the magic:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="LDapServicesSoap" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="address"
binding="basicHttpBinding" bindingConfiguration="LDapServicesSoap"
contract="LDapServices.LDapServicesSoap" name="LDapServicesSoap" />
</client>
</system.serviceModel>

Getting Error Access denied while consuming WSDL endpoint

I need to access web service which required HTTP basic authentication and I consumed successfully using SoapUI.
SoapUI
Now I need to implement in .net.
I created a new C# Console project in Visual Studio and added a web reference for https://itestapi.tracelink.com/soap/snx/snrequest?wsdl
Below is my code and I am getting Access Denied
C# code
ServiceReference1.snrequestClient snx = new ServiceReference1.snrequestClient();
snx.ClientCredentials.UserName.UserName = "abc#gmail.com";
snx.ClientCredentials.UserName.Password = "xyz#2018";
ServiceReference1.objectKey objectKey = new ServiceReference1.objectKey
{
Name = ServiceReference1.objectIdentifierType.GTIN,
Value = "1111111"
};
ServiceReference1.ReferenceDocuments ReferenceDocuments = new ServiceReference1.ReferenceDocuments();
snx.serialNumbersRequest("11111", "11111", ServiceReference1.idType.GS1_SER, ServiceReference1.encodingType.SGTIN, 2, objectKey, "", ReferenceDocuments);
App.config
<bindings>
<basicHttpBinding>
<binding name="snrequestPortBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
<binding name="snrequestPortBinding1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://itestapi.tracelink.com:443/soap/snx/snrequest"
binding="basicHttpBinding" bindingConfiguration="snrequestPortBinding"
contract="ServiceReference1.snrequest" name="snrequestPort" />
</client>

How can I configure a TransportSecurityBindingElement for a CustomBinding within a web.config?

I have the following (reduced) code that I'd like to configure through a web.config
var security = new TransportSecurityBindingElement();
security.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());
var binding = new CustomBinding(security);
Is it possible to configure this custom binding using the web config? If it is possible how could I configure the endpoint supporting token parameters? I've tried The following config, however it does not validate against DotNetConfig.xsd:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="SomeBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<transportSecurity> <!-- Fails validation -->
<!-- How do I configure the EndpointSupportingTokenParameters -->
</transportSecurity>
</binding>
</customBinding>
</bindings>
<client>
...
</client>
</system.serviceModel>
I think you just use customBinding/security, perhaps with an authenticationMode of UserNameOverTransport:
<system.serviceModel>
<bindings>
<customBinding>
<binding>
<security authenticationMode="UserNameOverTransport" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
Failing that, you could try adding the token manually to issuedTokenParameters:
<system.serviceModel>
<bindings>
<customBinding>
<binding>
<security authenticationMode="UserNameOverTransport">
<issuedTokenParameters tokenType="http://schemas.microsoft.com/ws/2006/05/identitymodel/tokens/UserName" />
</security>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
(tokenType stolen from UserNameSecurityTokenParameters)
To be honest, it's probably so much hassle that it's easier to just do it in code. If you need to to be different per environment, define the factory in the config and use DI to use it to create the binding.

WCF - The maximum nametable character count quota (16384) has been exceeded while reading XML data

I'm having a WCF Service that uses wsHttpBinding. The server configuration is as follows :
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
At the client side I'm including the Service reference of the WCF-Service. It works great if I have limited functions say 90 Operation Contract in my IService but if add one more OperationContract than I'm unable to Update the Service reference nor i'm able to add that service reference. In this article it's mentioned that by changing those config files(i.e devenv.exe.config, WcfTestClient.exe.config and SvcUtil.exe.config) it will work but even including those bindings in those config files still that error pops up saying
There was an error downloading 'http://10.0.3.112/MyService/Service1.svc/mex'.
The request failed with HTTP status 400: Bad Request.
Metadata contains a reference that cannot be resolved: 'http://10.0.3.112/MyService/Service1.svc/mex'.
There is an error in XML document (1, 89549).
The maximum nametable character count quota (16384) has been exceeded while reading XML data. The nametable is a data structure used to store strings encountered during XML processing - long XML documents with non-repeating element names, attribute names and attribute values may trigger this quota. This quota may be increased by changing the MaxNameTableCharCount property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 89549.
If the service is defined in the current solution, try building the solution and adding the service reference again.
Any idea how to solve this????
Try the following:
In the installation directory of your Visual Studio where devenv.exe is located (e.g. C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE) add this section to the devenv.exe.cofig
<system.serviceModel>
<client>
<endpoint binding="customBinding" bindingConfiguration="largeServiceBinding" contract="IMetadataExchange" name="http" />
</client>
<bindings>
<customBinding>
<!-- NOTE: The binding name must be the same as specified in the config file of the wcf service -->
<binding name="largeServiceBinding" >
<textMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
in the app.config of your WCF-service add the same binding:
<bindings>
<customBinding >
<!-- NOTE: The binding name must be the same as specified in the devenv.exe.config file located ..\Common7\IDE folder of the VS installation directory -->
<binding name="largeServiceBinding" >
<textMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
</binding>
</customBinding>
</bindings>
Note that the name attribute of the binding tags from the two files must match (e.g. largeServiceBinding)
Finally add the following mex endpoint into your service tag:
<endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
this may look like this:
<services>
<service behaviorConfiguration="MyServiceBehavior"
name="MyService.MyService">
<endpoint address="" binding="wsHttpBinding" contract="MyService.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/MyService/MyService/" />
</baseAddresses>
</host>
</service>
</services>
I know it has been a while, but I got the same problem and found other (simpler) solution in codeproject
In the solution given there the values are set in the code rather than the .config file.
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.MaxReceivedMessageSize = 50000000;
binding.ReaderQuotas.MaxArrayLength = 50000000;
binding.ReaderQuotas.MaxStringContentLength = 50000000;
binding.ReaderQuotas.MaxNameTableCharCount = 50000000;
EndpointAddress endpoint = new EndpointAddress(new Uri("https://server/EWS/Exchange.asmx"));
ExchangeServicePortTypeClient ews = new ExchangeServicePortTypeClient(binding, endpoint);
However, I changed the values in the relevant values in the .config file ( in both the <binding> and the <readerQuotas> sections) and solved the problem (rather than adding custom bindings):
<binding name="ITransactionProcessor" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="50000000" maxBufferPoolSize="524288" maxReceivedMessageSize="50000000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="50000000" maxArrayLength="50000000"
maxBytesPerRead="4096" maxNameTableCharCount="50000000" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
I hope this will help somebody :)
One thing to recognize is that the message refers to the svcutil reader quotas not the service ones! Svcutil has a limit on how much metadata it can read. This limit can be changed with a config file. The solution is to create a config file for svcutil and place it in the same folder as the tool. Next time you run svcutil, the config file values will be taken into account.
http://geekswithblogs.net/claraoscura/archive/2007/08/20/114806.aspx
in your app.config or dll.config on the the client add:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="myMex" maxReceivedMessageSize="1024000"> <!-- modify this to avoid stupid error -->
<readerQuotas maxNameTableCharCount="163840" /> <!-- DO NOT touch this one -->
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
...
<client>
<endpoint binding="netTcpBinding" bindingConfiguration="myMex"
contract="IMetadataExchange" name="net.tcp" />
...
</client>
</system.serviceModel>
</configuration>
And there you go!
This is one of the really annoying things with WCF and as often google just yields you alot of bs. Wasted tons of time with this.

Categories

Resources