WCF client config: centralized endpoint address - wcf

i've a WCF client wicht refers to multiple services hosted in the same machine. like this example
<client>
<endpoint address="net.tcp://localhost:8731/TrackingService" binding="netTcpBinding" ...
</endpoint>
<endpoint address="net.tcp://localhost:8731/CommonService" binding="netTcpBinding"...
</endpoint>
</client>
is it possible to modify my app.config in order to keep the
net.tcp://localhost:8731
part of endpoint address in a different variable, so when i'll deploy i have to change it once?
Maybe a programmatically clever way to do this? My only need is to change "address:port".
Thank you in advance

No, unfortunately, on the client side, there's nothing like a <baseAddress> like on the server side, which you can set globally.
Each endpoint declaration must have the entire, complete URL in it, I'm afraid.
Marc

You can always programmatically create your client and read the address from a normal appconfig value. Like this
MyClient client=
new MyClient(new BasicHttpBinding(), new EndpointAddress(ConfigurationManager.AppSettings.Get("ServiceAddress");)

Related

Asp.NET Core 2.2 WCF Warning: Policy

I'm trying to add wsdl using WCF. But at first I get an warning like this;
enter image description here
Here is the details:
The following Policy Assertions were not Imported:
XPath://wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:binding[#name='zz_binding_SOAP12']
Assertions:
<saptrnbnd:OptimizedXMLTransfer xmlns:saptrnbnd='http://www.sap.com/webas/710/soap/features/transportbinding/'>..</saptrnbnd:OptimizedXMLTransfer>
<sapattahnd:Enabled xmlns:sapattahnd='http://www.sap.com/710/features/attachment/'>..</sapattahnd:Enabled>
The following Policy Assertions were not Imported:
XPath://wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:binding[#name='zz_binding']
Assertions:
<saptrnbnd:OptimizedXMLTransfer xmlns:saptrnbnd='http://www.sap.com/webas/710/soap/features/transportbinding/'>..</saptrnbnd:OptimizedXMLTransfer>
<sapattahnd:Enabled xmlns:sapattahnd='http://www.sap.com/710/features/attachment/'>..</sapattahnd:Enabled>
The optional WSDL extension element 'Policy' from namespace 'http://schemas.xmlsoap.org/ws/2004/09/policy' was not handled.
XPath: //wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:portType[#name='zz_test_web_structure']/wsdl:operation[#name='ZzTestWebService']
The optional WSDL extension element 'Policy' from namespace 'http://schemas.xmlsoap.org/ws/2004/09/policy' was not handled.
XPath: //wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:portType[#name='zz_test_web_structure']
I still can't run the wcf service after adding it. Does anyone know about this?
Microsoft WCF Web Service Reference Provider tool based on the Mex service endpoint, namely metadata exchange service endpoint instead of the Web service definition language(WSDL page).
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="basicHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
Or,
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
If you prefer to generate a client proxy class by using WSDL, you could try the SVCUtil.exe tool.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/servicemodel-metadata-utility-tool-svcutil-exe
All the above ways can generate a client proxy class.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Besides, In WCF4.5 there is a new feature called SingleWSDL, which contains the whole WSDL with the related schema. It could be consumed perfectly by a third-party system.
What is the difference between ?wsdl and ?singleWsdl parameters
https://learn.microsoft.com/en-us/dotnet/framework/wcf/whats-new
Feel free to let me know if there is anything I can help with.

WCF Routing backup list in client

Is it possible to define a WCF backup list in a client, so that a single-point-of-contact routing service is not nessasary?
I have two services implementing the same contact (interface). If the first service is not avaliable I would like the client to know that the backup service is to be used.
Is this possible or do I have to create a routing service (single-point-of-contact) that the client would communication with?
<client>
<endpoint address="http://localhost:49192/OrdinaryCustomerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICustomer"
contract="OrdinaryCustomerServiceReference.ICustomer" name="OrdinaryCustomerService" />
<endpoint address="http://localhost:49860/PremiumCustomerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICustomer"
contract="PremiumCustomerServiceReference.ICustomer" name="PremiumCustomerService" />
</client>
<routing>
<backupLists>
<backupList name="CustomerBackupList">
<add endpointName="PremiumCustomerService"/>
</backupList>
</backupLists>
</routing>
Just an idea but i have a similar issue and i have been thinking about creating a routing service on the client (IIS webserver in my case) so that all request on the webserver can fail over to different web services. We also have multiple webservers for fail over so i would put a router on each.
Not ideal but best solution i have found so far. If the router on the IIS box goes down chances are the IIS will be down as well and therefore our system would have kicked over tot he other webserver anyway.
We also have proper wfc routers with backup for our middle teir but before it was a manual change to the webservice to handle this.

What Service name does one use for Workflow WCF Services (XAMLX)

I am trying to figure out how to provide endpoints etc to a WF Service that I created (MyFoo.xamlx). Typically when you create a Service you need to have the Service name="" reflect the type of service you've created? ie by filling out something like this:
<Service name="MyNameSpace.Foo" behaviorConfiguration="myFooBehaviorConfig">
This works in a typical .svc scenario and I can get that working fine. Only how does one map this concept across to a .xamlx service? In that if I have Foo.xamlx putting that inside the Service name doesn't work - or doesn't appear to work (as in no metadata is enabled).
If i then remove the behaviorConfiguration attribute from the Service and also remove the myFooBehaviorConfig from the <behavior/> tag - in that it essentially then takes on more of a global setting for the web config - boom! I can see the .xamlx exposed methods/operations?
<serviceBehaviors>
<behavior name="foo" >
vs
<serviceBehaviors>
<behavior >
At first this is great, no effort required but at the same time I don't want devs to access HTTP endpoints or netpipe for that matter. I only want them to come in through net.tcp port I specify. In order to do that I need to match the <Service name=""/> to the xamlx somehow?
I've also tried using the trick of creating an empty .svc file and then pointing to the xamlx that way (so that the devs always assume its a .svc and not a .xamlx)
<%# ServiceHost Language="C#" Debug="true" Service="ActivityHubService.xamlx" Factory="System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory" %>
Again, if I remove naming the behavior etc this also works via foo.svc ..but i just can't seem to crack the whole matching a <service> with a freakin xamlx!! :) hehe.
Frustrating..
Anyone an expert in this space?
I'm gonna give this one to GuerreroTook as although the answer he gave was partially in the same area of right it did however spark a moment of "yeah maybe its that simple.." thinking..
The solution was this:
<services>
<service name="ActivityHubService" behaviorConfiguration="foo">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="netTCPStreamedBinding" contract="IService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://synapse.hub.security:669/SynapseHubSecurity/ActivityHubService" />
</baseAddresses>
</host>
</service>
</services>
Then inside a service i called PingService.svc I put this:
<%# ServiceHost Language="C#" Debug="true" Service="ActivityHubService.xamlx" Factory="System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory" %>
That seemed to have done the trick!! :)
Not sure why but i swore I did this like 3x and it failed..but...i am also in need of sleep..
Hopefully this will help others in the same jam down the track.
Based on what you ask, I understand that you need to expose a WF Workflow as a WCF service and you want client to call directly WF through WCF infrastructure, is that right?
The problem you facing is that you need to provide the full qualified name of the class in order to the factory to find and activated your WF workflow. If you have a typical WP project inside VisualStudio the Full Qualified Name is the name of the project + the class name, try with this.
When you build your workflow xaml file the compile will generate a class that hold and the code and logic, and following the same behavior of the xaml (WPF and Silverlight) compiler the name of the class will be the same of the file (.xamlx)

Getting machine name in the svcutil when hosting WCF service

I have a domain/website(HTTR.abc.com) hosted in inetmgr in IIS in production servers.
I want to host a WCF service under the domain HTTR.abc.com
The web.config of my WCF service is as follows
<services>
<service behaviorConfiguration="HTTR.Business.HTTRContextServiceBehavior" name="HTTR.Business.HTTRContextService">
<endpoint address="http://machinename:83/GTYEBus/abcService.svc" binding="wsHttpBinding" contract="HTTR.Business.IHTTRContextService">
</endpoint>
</service>
</services>
When i run the URL
"http://HTTR.abc.com/GTYEBus/abcService.svc" the page shows properly but it is showing
WSDL file pointing to "http://machinename:83/GTYEBus/abcService.svc?WSDL"
I would want the page to show the WSDL with the same path as the .svc path, that is it should show as "http://HTTR.abc.com/GTYEBus/abcService.svc?WSDL" instead of
"http://machinename:83/GTYEBus/abcService.svc?WSDL"
I came across this one while tring to find a resolution to the same issue.
This ended up being a issue with the site not having a host name.
In IIS7.5, simply add in the host name into the host header on the binding. If it is https, the host header may be protected. You'll need to make the certificate become a pseudo wildcard cert by putting a * as the start of the certificates friendly name. Then the host name will be editable.
This link has a good description of the resolution in IIS6
In the serviceMetadata section of the web.config you can include the attribute externalMetadataLocation and refer it to the "http://httr.abc.com/GTYEBus/abcService.svc?wsdl" location. Example:
<serviceMetadata externalMetadataLocation="http://httr.abc.com/GTYEBus/abcService.svc?wsdl" />
Here is the MSDN reference on the serviceMetaData config section: http://msdn.microsoft.com/en-us/library/ms731317.aspx.
This does not require any additional IIS configuration and is much more scalable.
Hope this helps.

How to configure WCF service from code when hosted in IIS?

My WCF service exposes an https AND an http endpoint. Apart from the SSL they are identical. They map to the same code.
The ultimate intention is for external users to connect via https, internal users to use http.
In development this gives me a problem. Cassini, the development web server packaged in VS, hates SSL.
I'm wondering if I can configure the service from code, so when running under Cassini, I would not configure https.
Hence the question - How do I configure the service from code if it is IIS hosted? I'd be very happy with alternative answers on how I can persuade Cassini to NOT complain about the https part of the configuration.
"IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really."
Not too close to the truth. Exactly in the SVC file of your service there is attribute named Factory. Where you can specify the the class and the assebly where the class is located. This class may be your own descendant of Web|DataServiceHostFactory
So your svc markup would look like this
<%# ServiceHost
Language="C#"
Debug="true"
Service="name.space.myService"
CodeBehind="name.space.myService.svc.sc"
Factory = "name.space.WebServiceHostFactoryEx, assembly.name"
%>
The WebServiceHostFactory will be created for every service hit and will recreate your host the way you want it.
You will also need to inherith WebServiceHost and create it the way you need it with certain endpoins, behaviors, addresses, etc settings - whatever you like.
There is very nice post from Michele Bustamante here
EDIT: I figured out the above link is not working anymore, so here it is another one.
I am using this in IIS hosted enviroment for couple of services that are initialized same way.
When you're hosting in IIS, you're leaving a lot of care taking into the realm of IIS - you cannot really grab a hold of your service in this case.
IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really.
My solution would be different - externalize the <service> tag in your configuration file (web.config):
<system.serviceModel>
<services>
<service configSource="service.dev.config" />
</services>
</system.serviceModel>
In your dev environment, only expose the http endpoint - so your service.dev.config would look something like this:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
</service>
Create a second service.prod.config which then contains both endpoints - http and https:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
<endpoint name="secure"
address="....."
binding="basicHttpBinding" bindingConfiguration="secure"
contract="......" />
</service>
and reference that in your web.config on the deployment server.