Consuming WCF service in Com visible assembly - wcf

I have to consume a WCF service hosted in Windows Service using a COM Visible assembly.
I have a WCF Service that is hosted in Windows Service, I have to consume the service in a COM Visible assembly, I have created a COM + application and added a service reference to it. Below is the app.config.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="TcpEndpoint" 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="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://serverMachine:9600/DocumentsWcfService/Tcp"
binding="netTcpBinding" bindingConfiguration="TcpEndpoint"
contract="MysWcfService.IMysWcfService" name="TcpEndpoint" />
</client>
</system.serviceModel>
</configuration>
When I use this assembly in a classic ASP project and call the method that initializes the service I get the error as below. But when I refer the same WCF service in Console application, it works fine. Is there any specific changes required to consume in COM visible application.
Could not find default endpoint element that references contract 'MyWcfService.IMysWcfService' 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

COM server don't read normal config files so you either need to do it via code or use the following trick:
(Your COM server must be an .exe)
Go to dcomcnfg and create a COM+ application
In the COM+ application there is a setting "Application Root Directory". Enter the folder where your .exe is located
Add your com object to the COM+ application
Create a file named Application.manifest in the folder. The file must contain:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" />
Put your config file in the same folder. Note that the config file must have the exact name Application.config, not "myapp.exe.config"
Now the config file will work the same way as in your console application.

Try to read configuration with
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "MysWcfService.dll.config";
configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Then you can try to read some wcf config sections and configure your host programmatically (example):
ServicesSection servicesSection = (ServicesSection)configuration.GetSection("system.serviceModel/services");
ServiceEndpointElement endpoint = servicesSection.Services[0].Endpoints[0];
//use endpoint.Address
//use endpoint.Binding
//use endpoint.Contract

Related

Is it possible to have a WCF client running in an ASPX call an SVC via net.pipe in another site on the same machine?

I have two web sites-- one with an aspx file, one with a wcf service with two end points, one http and one named pipes. They both run on the same machine, so they seemed like a candidate for using the net.pipe binding.
The aspx file creates a service client and attempts to call the net.pipe. And I get this:
"Server Error in '/dev' Application.The message could not be
dispatched because the service at the endpoint address
'net.pipe://localhost/netNamedPipeBinding' is unavailable for the
protocol of the address."
Googling suggest this could be a security problem (no permissions errors are the same as no listener errors), but I've already granted NTFS rights to the [NETWORK] user group to the websites files with the services and no change.
The site with the aspx is using Forms authentication (i.e. not windows auth) and the service website is anonymous auth. The web.config's have the net.pipe security set to ="None"
Locally, this works fine-- although I have to run the named pipes host in a console app since the Visual Studio Dev Server can't do named pipes. Also, the Http endpoint works fine on IIS.
It's running .NET 4.0, IIS 7.5, Win2008.
IIS Config
As far as I can tell,
net.pipe has been enabled for the service website, with config info of *
WAS is installed and enabled, (via windows features)
the net.pipe listener Windows service is enabled.
Each website is anonymous access (auth is done by a 3rd party single sign on sever)
Each website has it's own app pool (probably not relevant)
The service site is in web garden mode (probably not relevant)
Service Config (Running on IIS on same machine, different VDIR)
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="netNamedPipeBindingConfig" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport protectionLevel="EncryptAndSign" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<services>
<service name="MyService">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/" />
</baseAddresses>
</host>
<endpoint
address="netNamedPipeBinding"
bindingConfiguration="netNamedPipeBindingConfig"
binding="netNamedPipeBinding"
contract="IMyService" >
</endpoint>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client Config (ASP.NET website, same machine, different VDIR from service)
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_IMyService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport protectionLevel="EncryptAndSign" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<client>
<endpoint
address="net.pipe://localhost/netNamedPipeBinding"
binding="netNamedPipeBinding"
bindingConfiguration="NetNamedPipeBinding_IMyService"
contract="MyService.IMyService"
name="NetNamedPipeBinding_IMyService">
</endpoint>
</client>
</system.serviceModel>
(Service & contract names changed to protect the innocent)
The C# isn't anything special, just the Add-Service-Reference generated proxy. (And all that code works fine with the wsHttp binding
You cannot set the base address of a named pipe when it is hosted in IIS in this fashion. As a result the service can not be found by the client. Look at the answer here for more details:
controlling-the-name-of-a-named-pipe-when-hosting-wcf-net-pipe-binding-in-iis

Calling a webservice from a C# dll from within CLASSIC ASP

I'm a windows dev with very little knowledge of web applications and ASP. I'm trying to create a C# dll (which is making a webservice call) for someone, that is being called from a CLASSIC ASP app.
It all started from a WinForms test app that successfully loaded a WSDL and called that web service. Now the requirement is to take the test app functionality, move it to a dll and call that dll from the ASP app. I naively left the appconfig file there, and when that dll was called, he got this well known error:
Could not find default endpoint element that references contract Service1.MyService 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.
I understand that classic asp doesn't have config files - I read a lot of posts about it, and most of the relevant ones mention to use BasicHTTPBinding and provide an endpoint address on the fly. How do I do that? Any examples?
I saw this answer:
All I needed to do is to create a BasicHTTPBinding and provide an endpoint address on the fly.Then create a new instance of the web service using the created binding and endpoint address.
But i'm not sure how to do it.
This is the appconfig that worked for the winforms app:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService">
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None"
realm="" />
</security>
</binding>
<binding name="BasicHttpBinding_ICustomerService" 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>
<client>
<endpoint address="https://MyService.svc"
behaviorConfiguration="custom" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMyService" contract="MyService.IMyService"
name="BasicHttpBinding_IMyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="custom">
<customInspector />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="customInspector" type="CustomBehaviors.CustomBehaviorExtensionElement, CompeteDataServiceTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
You will need to configure the service through code, as there is no config file in this case. See Configuring WCF Services in Code.

WCF consume by dotnet winfom client and config entry

i am new in WCF but i am bit familiar with web service (ASMX file)
i have couple of question on wcf client config entry
when we create any web service (ASMX) proxy then nothing add in config file like below entry but in case of WCF the below entry adds. i just need to know the significant of the below entry.
1) if i delete these below entry then what will happen....can't i call the service from the client side?
2) just tell me when we call web service from client side then how do i say that which endpoint address my service will use to call service if there are more than one endpoint address added in client side ?
3) how do i explicitly mention web service url from cient side when i will make a service call?
<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>
Yes these are important configuration that are required by WCF. Either you provide it through config file or your code.
1) You need to provide it some where. If you take them fro config . You should be doing it in code.
2) WCF has basic rule of ABC . Address , Binding and Contract. Again you don't have to say anything if its already in your config file.
For multiple clients . You can also mention the endpoint name from your config file. ForExample
MyClient someClientObject = new MyClient("WSDualHttpBinding_ICommService");
3) By default, when you Add Service Reference operation, WCF Runtime gets you a client side proxy .
You can do it like this in a simple way. ParameterLess.
MySVCClient svcproxy = new MySVCClient ();
You need to have entry with your service contract .
You can also use as follows with constructor ... using endpoint Adddress and Bidning etc.
BasicHttpBinding myBinding= new BasicHttpBinding(SecurityMode.None);
EndpointAddress endpointAdd= new EndpointAddress("http://localhost/CommService/");
MySVCClient svcproxy = new MySVCClient (myBinding, endpointAdd);
Since you are defining everything in code here. You don't need anything in config file.

Named-Pipes client won't start

I have a class library that is supposed to build a connection to an existing named-pipes server. The error I get is:
Could not find endpoint element with name 'internal' and contract 'SelectedStudentReference.ISelectedStudent' 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 name could be found in the client element.
Here is xml from dll.config:
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="internal" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport protectionLevel="EncryptAndSign" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<client>
<endpoint address="net.pipe://localhost/SelectedStudent" binding="netNamedPipeBinding"
bindingConfiguration="internal" contract="SelectedStudentReference.ISelectedStudent"
name="internal">
<identity>
<userPrincipalName value="name#company.org" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Here is the code I use to instanciate the client, and also where it throws the error:
using AwardManager.SelectedStudentReference;
if (_client == null) _client = new SelectedStudentClient("internal");
I know the server is running and the error message only mentions the client failure. Is there any problem doing this from a class library? The install program did not copy the .config out with the dll, I did that manually, so I'm not sure the .dll is paying attention to the .config.
This is a registered COM-visible dll that is instanciated and called by another process. I'm not able to add this system.serviceModel to the .config for that other process.
I could build the client in code, if that would work and I had some examples of how to accomplish that.
I could also use some help with the userPrincipleName. It doesn't seem correct for it to use my credentials. Shouldn't it specify the user's credentials, or some generic credentials? Does it even need to be included in the client configuration?
Thanks
This stuff needs to be in the config for the exe that hosts your DLL. A DLL does not have a stand-alone config - or at least .NET does not read it unless you do something custom.
If you can't modify the hosting EXEs config, you're probably going to have to build this configuration in code.

WCF cannot connect to endpoint after successfully adding service reference

I've successfully published a WCF service on our production server. I can navigate to the page and see the default WCF page.
I can add the service via "Add Service Reference" to a client on my computer. I can also "Update Service Reference" with no problems what so ever.
The service was confirmed to work on my local computer with and without the client by running the default debugger that comes with VS2010.
When trying to call a service method (from the server hosted service), I receive this exception..
There was no endpoint listening at that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
InnerException...
{"The remote server returned an error: (404) Not Found."}
I've also tried running a client on the server itself to see if I can connect but I get the same error.
I even tried just deploying the basic WCF service that's created for you when you create a WCF service library (very basic), changed nothing, deployed successfully, and get the same error.
What am I doing wrong? I've went down the road of IIS configurations, SSL certificates, etc but nothing seems to fix it. I feel as though I'm missing something very basic here.
EDIT CLIENT CONFIG...
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" 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>
<client>
<endpoint address="http://SERVER_NAME.DOMAIN_NAME.com/TestService/TestService.Service1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
Some pitfalls to check:
1) Check if the service URL is correct on your configuration files. This includes the protocol. It happened to me recently: the .config file had "http://" and the webserver was only accessible through HTTPS.
2) Disable the "required client certificate" setting on IIS.
3) If your service is inside an asp.net application, check if there are any restrictions of Authentication / Authorization in place. Allow anonymous access to your .SVC