How to set up a WCF client using wsDualHttpBinding in code? - c#

I have a need to connect to a WCF service I wrote without having to deploy an app.config for the client application I'm writing. However, I've been having a very difficult time trying to figure out how to set up things from the client side in code. This is as far as I've gotten... does anyone have any ideas what I need to do to get this to work? I'd really appreciate it.
This is the code I've got so far:
String baseAddress = "http://localhost/CommService";
WSDualHttpBinding binding = new WSDualHttpBinding();
binding.Name = "WSDualHttpBinding_ICommService";
binding.ClientBaseAddress = new Uri(baseAddress);
binding.ReliableSession.Ordered = true;
binding.ReliableSession.InactivityTimeout = new TimeSpan(0, 10, 0);
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
binding.SendTimeout = new TimeSpan(0, 0, 5);
InstanceContext context = new InstanceContext(this);
client = new CommServiceClient(context, "WSDualHttpBinding_ICommService");
client.Endpoint.Binding = binding;
And this is my client app's app.config:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_ICommService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:00:05"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/CommService/"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ICommService"
contract="Services.ICommService" name="WSDualHttpBinding_ICommService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>

You can easily achieve what you want. See code below :
Uri baseAddress = new Uri("http://localhost/CommService");
WSDualHttpBinding wsd = new WSDualHttpBinding();
EndpointAddress ea = new EndpointAddress(baseAddress, EndpointIdentity.CreateDnsIdentity("localhost"));
client = new CommServiceClient(new InstanceContext(this), wsd, ea);
Let me explain a bit :
first we create an instance of a WSDualHttpBinding with the default settings (those are the exact ones the generated app.config has). If you want to modify any of the settings, you can modify them trough the exposed properties.
then we create an EndPointAddress with th desired URL and identity. No need to link it with a binding because we will link all of them in the Service Client constructor.
lastly we create the Service Client. One of the contructor overloads allows us to specify a Binding and an Endpoint Address.
in general every element available in the app.config file has an associated Class in .NET code and every attribute or child element has an associated Property in the specified class.

Related

Connect to a web service using a mapped configuration file

We have a CRM2011 plugin running async which needs to connect to a webservice to get some missing data. The way i'm trying to solve this is to use a webservice client, made using 'add service reference'.
But for configuration i don't want to hard code the endpoint and binding. So i thought i would just load the configuration for the webservice using OpenMappedExeConfiguration like so.
var config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap{ ExeConfigFilename = #"c:\Path\to\config.xml"}, ConfigurationUserLevel.None);
The config file is loaded... however it is not visible to the client. Because calling
var client = new MyDataServiceClient();
will throw
InvalidOperationException :
Could not find default endpoint element that references contract
'MyDataService.IMyDataService' 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.
The configuration file i'm using is:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyDataService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="https://integrationservices-dev.thecompany.com/MyDataService/MyDataService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyDataService"
contract="MyDataService.IMyDataService"
name="BasicHttpBinding_IMyDataService" />
</client>
</system.serviceModel>
</configuration>
I know i could initialize a binding and endpoint and give those to the MyDataServiceClient(Binding, Endpoint) constructor. But i rather don't want to write my own configuration loader logic.
Is there a way to make the loaded config known to the code constructing the client? If not what other options are there ?
You are trying to read a exe configuration but you are on Web Context, I think you must use OpenWebConfiguration.
In short this command opens the Web-application configuration file as a Configuration object.
Alternatively you can add your configuration into web.config on CRM site
See this Stackoverflow article
See MSDN

.NET Web Service Using WEB CONFIG Settings Hard Coded Net TCP

I wanted to confirm something.
Below is how I am spinning up a call to my WCF web service in my ASP.NET application.
var xml = "my xml string";
var ep = new EndpointAddress("http://myendpoint");
xml = new Proxy.ServiceClient(new NetTcpBinding(), ep).getNewXML(new Proxy.CallContext(), xml);
My web config looks similar to below. My question is, even though these settings are in the web config, the fact that my calls above are newing up the a service client and fresh New TCP binding everytime tell me that these settings aren't being referenced. Is this correct based on above?
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_SCSService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://myendpoint"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_SCSService"
contract="Proxy.Service" name="NetTcpBinding_SCSService">
<identity>
<userPrincipalName value="user#user.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
That's correct. In this case, you are not using the configuration settings found in the config file.
Proxies typically derive from the abstract class ClientBase<T> which provides several different ways to create an instance of a client proxy. Some of the constructors listed will use all of the config file while others will attempt to use the config file to fill in the information that has not been explicitly supplied in the constructor. There are even constructor overloads which do not use the configuration file at all which ClientBase<TChannel>(Binding, EndpointAddress) is one of them.
If you wanted to use what was in the application configuration file, you could use:
var client = new Proxy.ServiceClient("NetTcpBinding_SCSService");

Issues connecting to a web service in C#

I am using a third party wsdl to connect to a service. I have been provided a security certificate and a username / password.
I have:
Installed the certificate on my Windows 7 machine
Ensured it has the correct permissions
Have the correct location for the API stored in the web.config
The code fails each time. The error messages change, but they include:
Authentication failed because the remote party has closed the transport stream.
An existing connection was forcibly closed by the remote host
Could not create SSL/TLS secure channel
This is the code I am executing:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
//Third party client
var client = new ConnectionPortClient();
//Including these two lines or not does not affect the outcome
//client.ClientCredentials.UserName.UserName = "username";
//client.ClientCredentials.UserName.Password = "password";
client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(#"C:\..\cert.p12", "password", X509KeyStorageFlags.MachineKeySet);
var results = client.getResults("");
And here is the relevant part of the web.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="assessmentBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://endpoint/" binding="basicHttpBinding"
bindingConfiguration="assessmentBinding" contract="API.Assessment"
name="assessmentSOAP" />
</client>
</system.serviceModel>
Any thoughts on what's going on here?
you use Certificate message credential type but you are trying to set up UserName/Password for UserName message credential type - this is wrong. check the article about Message Security with a Certificate Client

C# WCF Client takes too long to opened state (DuplexClientBase<T>.Open())

I'm having a little problem with a WCF client. First, allow me to explain and give you details.
I'm currently developing a system, and I was thinking in separate the main application because I designed it to be updated with dlls. So I found MEF, and began to read a lot about it. But there was problem with MEF, it locks the file, no write. Then I found shadow copy. So now I placed the client in another AppDomain in the main Application. I've read that communication cross domains is possible through NET Remoting, so I made research and done it with WCF.
The main Application is the host, it loads the assembly in a new domain and starts the client. As the client is a DLL, there is no AppConfig file to load bindings, endpoints. I've created a class that helps me with that, so the config is added programatically.
Finally, it works!
But there is a little thing I don't think is ok. In the client, when the instruction DuplexClientBase.Open() is executed, it takes 20 seconds to open. I think is not OK 'cause when I move the client to a EXE (remember is a DLL and the config is added programatically) it doesn't take all that time.
Maybe is something wrong in the config, but I can't find it. So here are the souce code files. First, this is the App.config file, when the client is in a console application:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="TcpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
<wsDualHttpBinding>
<binding name="HttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8080/ProtoServicio/EPServicioTcp"
binding="netTcpBinding" bindingConfiguration="TcpBinding"
contract="TestServicio.IServicio" name="TcpBinding">
<identity>
<userPrincipalName value="OlinzerLaptopV\Olinzer" />
</identity>
</endpoint>
<endpoint address="http://localhost:8081/ProtoServicio/EPServicioHttp"
binding="wsDualHttpBinding" bindingConfiguration="HttpBinding"
contract="TestServicio.IServicio" name="HttpBinding">
<identity>
<userPrincipalName value="OlinzerLaptopV\Olinzer" />
</identity>
</endpoint>
</client>
</system.serviceModel>
And now, this is the code that creates the binding and endpoint:
internal static Binding GetBinding()
{
WSDualHttpBinding binding = new WSDualHttpBinding();
TimeSpan span = new TimeSpan( 0, 1, 0 );
binding.Name = "HttpBinding";
binding.CloseTimeout = span;
binding.OpenTimeout = span;
binding.ReceiveTimeout = span;
binding.SendTimeout = span;
binding.BypassProxyOnLocal = false;
binding.TransactionFlow = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas = new XmlDictionaryReaderQuotas();
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 8192;
binding.ReaderQuotas.MaxArrayLength = 16384;
binding.ReaderQuotas.MaxBytesPerRead = 4096;
binding.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.ReliableSession = new ReliableSession();
binding.ReliableSession.Ordered = true;
binding.ReliableSession.InactivityTimeout = span;
binding.Security.Mode = WSDualHttpSecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
return binding;
}
The file created by the code only contains the Http Endpoint. Maybe adding the tcp endpoint could make the diference, but, I have no idea how to make it. The function above is called by the constructor of the ClientClientBase class.
ServiceModel.DuplexClientBase<Servicio> MyClient = new ...<Servicio>(new InstanceContext(this), GetBinding(), GetEndpoint());
Feel free to notify me if you need anything else.
You are doing cross AppDomain communication within single process and you are using WsHttpBinding? Do you understand how big overhead this has? It also highly increases complexity of your application deployment. It is probably not source of your main problem but I would start with:
Replacing WsDualHttpBinding with NetNamedPipeBinding
To diagnosing your issue start with WCF tracing and check which operation on both client and server takes a long time - there can be problem with some security resolving because your setting uses message security.

Call web services from event sink

I am using C# to build an event sink to monitor a specific exchange server inbox.
My implementation is based on this example: http://www.codeproject.com/KB/exchange/ManagedEventSinks.aspx?fid=382114&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26#xx0xx
Instead of the functionality described in the example i am trying to send some specific information to a web service.
I use visual studio to add the service reference to my class library and the following code to call the single method in the web service:
public void OnSave(IExStoreEventInfo pEventInfo, string bstrURLItem, int lFlags)
{
try
{
Message iMessage = new MessageClass();
iMessage.DataSource.Open(bstrURLItem, null,
ADODB.ConnectModeEnum.adModeRead,
ADODB.RecordCreateOptionsEnum.adFailIfNotExists,
ADODB.RecordOpenOptionsEnum.adOpenSource, "", "");
string sub= iMessage.Subject;
string body = iMessage.HTMLBody;
MyWSSoapClient wsc = new MyWSSoapClient();
wsc.SingleMethodinWS(sub, body);
}
catch (Exception ex)
{
}
}
After i build the COM component and add the event sink to the inbox and test it i get the error:
Could not find default endpoint element that references contract 'MyWS.MyWSSoap' 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.
at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
at System.ServiceModel.ChannelFactory`1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
at System.ServiceModel.EndpointTrait`1.CreateSimplexFactory()
at System.ServiceModel.EndpointTrait`1.CreateChannelFactory()
at System.ServiceModel.ClientBase`1.CreateChannelFactoryRef(EndpointTrait`1 endpointTrait)
at System.ServiceModel.ClientBase`1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase`1..ctor()
at ReplyParserEventSink.AnswerQuestionWS.AnswerQuestionWSSoapClient..ctor()
at ReplyParserEventSink.AsyncParser.OnSave(IExStoreEventInfo pEventInfo, String bstrURLItem, Int32 lFlags)
EDIT:
This is what i found in the app config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyWSSoap" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<endpoint address="http://127.0.0.1/MyProject/WebService/MyWS.asmx"
binding="basicHttpBinding" bindingConfiguration="MyWSSoap"
contract="MyWS.MyWSSoap" name="MyWSSoap" />
</system.serviceModel>
#Alexander: I tried what you said but i get the same error. Thanks
This is of course VS2010. Thing is with autogenerated code in app.config.
Check your app.config. This file contains all defenitions for bindings and endpoints. Just check you endpoints 1st, check whether your endpoint is described, and binding is defined too.
After that try:
MyWSSoapClient wsc = new MyWSSoapClient( "<endpointConfigurationName>" );
and see what would happen.
Also in <client> area you will find description of endpoints. Try to change binding to basicHttpBinding manually - that worked for me.
<endpoint address="http://service.address.com"
binding="basicHttpBinding" bindingConfiguration="yourService"
contract="Domain.Serice" name="serviceName" />
I am answering my own question because i have found and fixed the problem
The problem was that the information form the app.config file of the class library was not getting into the com component and therefore the error.
I fixed it by setting all my parameter values in my code from an external text file by following the example at: Consume a SOAP web service without relying on the app.config
Thanks for the suggestions everyone.

Categories

Resources