Today I started delving into WCF. I took to the tutorial at https://msdn.microsoft.com/en-us/library/ms734712(v=vs.110).aspx
I walked through this tutorial up until where you host the service host. The tutorial segment here told me start up the service and then navigate to the uri specified in code. When I did that my connection was refused. After a short while of messing around, I found that the base address was specified in the app.config as something else entirely. Navigating to that URI followed by the endpoint name took me where I wanted to go. I don't know how that address was generated, and don't really care all that much. What I'm more interested in is what purpose setting the base URI on the services plays when it seemingly has no effect whatsoever, and the actual base URI that is used comes from the app.config. It's required by the constructor of the ServiceHost type... so you would think its important. Can someone explain this to me?
If you look carefully at the two constructors of ServiceHost that are expecting Uris, the Uri parameter is prefixed with params.
In C#, it means you can pass as many Uris as you want, including zero.
Passing no Uri is interesting if you want to use the of the app.config.
If you got no configuration, you pass a type or an object and some Uris.
Then WCF creates a service that is expose all the interfaces of the service on all the Uris.
For instance if you ve got two interfaces in you service and you call :
var host = new ServiceHost(typeof(HelloService),
"net.tcp://localhost:7000/service1",
"net.pipe://localhost:8000/service1",
"http://localhost:9000/service1");
You 'll get 2x3 exposed endpoints
Most of the time ServiceHost are built without providing addresses.
Config is made in XML.
Regards
Related
For pure code-based WCF configuration, in .NET 4.0 one could configure a base address for a service when creating an instance of a ServiceHost (assuming a self-hosted scenario, which is suitable for my needs). While one could still do this with .NET 4.5, MSDN implies that using the new Configure() method is a better practice because it makes such code-based configuration a bit easier for self-hosted and a lot easier for web hosted scenarios (see Configuring WCF Services in Code).
The problem, however, is that though the object you have to work with inside the Configure method (a System.ServiceModel.ServiceConfiguration) has a BaseAddresses property it is read-only. Surely there must be a way to set the base addresses in code? My web searches have turned up not only nothing about this specific question, but no articles or posts about this Configure method at all, except for the single MSDN page I have referenced!
Looking in reflector what BaseAddresses property does:
// System.ServiceModel.ServiceConfiguration
public ReadOnlyCollection<Uri> BaseAddresses
{
get
{
return this.host.BaseAddresses;
}
}
I was unable to find any other method in ServiceConfiguration working with ServiceHost.BaseAddresses
Instance of ServiceConfiguration is created using ServiceHost instance:
// System.ServiceModel.ServiceConfiguration
internal ServiceConfiguration(ServiceHost host)
{
ServiceConfiguration.CheckArgument<ServiceHost>(host, "host");
this.host = host;
}
This means that ServiceConfiguration is just an extension to standard way of configuring ServiceHost. So I would suggest any old way of setting BaseAddress is still considered as the best practice (programmatic or using configuration).
This seems like it should be really simple, but I'm unable to figure this out.
I am adding a web service reference to my console application. The web service points against our production environment and I would like to test it against development. In VS2005 it was really easy to override the target URI of the service. Is it possible to do the same with VS2008? I would like to set the URI in code or via a config file.
I would really appreciate help with this. Thanks!
If you look in your .config, you should see <endpoint> elements that were added to the <client> section of <system.serviceModel>. Assuming you need to point at only one environment at a time you can simply edit the address attribute of those endpoints to point to whatever URL you want.
If you wanted to change this at runtime you need to use the constructor overload for the client proxy that was created. There should be several overloads that take a parameter called remoteAddress in many forms.
It seems that I was able to get around this issue by going to "Add Service Reference" -> "Advanced" -> "Add Web Reference". This gives me a reference in the form I am most familiar with. Now I was able to override the constructor with the URI parameter. Is that method frowned upon?
it looks like I am not able to succesfully move my WCF proxy code into a separate DLL (as opposed to an EXE as I can see in all the examples I have run into).
The reason I am trying to do this is that I would like my proxy code to be invoked by different clients (possibly unmanaged code), which might not know anything about WCF but just need to access to the services (through a Facade exposed by the proxy maybe?).
Whenever I move the following code that creates a new proxy to a different VS project within the same solution, I get the dreaded "Could not find default endpoint element that references contract 'localhost.IRemoteCommandService' in the ServiceModel client configuration section" exception.
localhost.RemoteCommandServiceClient proxy =
new localhost.RemoteCommandServiceClient();
The same code works smoothly whenever used within a Main method in the same project where the proxy code is (auto-generated from Visual Studio).
Any idea? I hope that the client code of my proxy does not need to have the service model XML configuration as the proxy, because that would defeat the purpose I am moving the WCF proxy code into a DLL in the first place.
Thanks,
Stefano
The endpoints are indeed normally specified in the configuration file. You must look at the serviceModel data in the config file, and copy it into your calling app.config - or you need to use the more verbose way of creating the proxies in your code (i.e. specifying the address, binding, configuration etc through code to the constructors).
If you don't want to have to endpoint configuration on the client, you'll have to embed it into your proxy dll by specifying everything in code.
Another option would be to use a dynamic proxy, like this one, which would allow you to not have the serviceModel in your client apps.
I have a scenario in which I'm going to need an arbitrary number of servers to provide the same SOAP web service. I would like to generate one set of proxy classes and be able to supply them with a location to point them at the different servers at runtime. Unfortunately, it looks as though the wsdl:port node (child of wsdl:service) requires the address of a specific server to be hardcoded. It appears that due to this the URL will be baked into my proxy classes. I know that I could potentially modify this by hand-editing the generated proxy classes, or modifying the code generation, but I'd really prefer not to resort to that. I feel like there's got to be a better way to solve this problem. I just want to decouple the interface definition from the location that the service will be residing at. I'm using VS2008 and C#.NET if that's of any help though best would be a language-agnostic (SOAP or WSDL specific) general solution to this problem.
Why don't you load balance the web servers and then create a DNS entry for the load balanced IP address....essentially creating a web farm. This will allow you to reference the hostname rather than the static IP addresses and if you ever need to change the IP address of the load balancer or the web servers it is a one time change. Plus you then have redundancy and performance control.
If you're using a WebReference (pre-WCF) to get to the web service, you can simply set the Url property on the web service proxy class after you create it.
For WCF, you can provide a different endpoint address to the proxy class constructor, rather than using the default (among other possible solutions).
No, in .NET you can change the URL at runtime.
Service svc = new Service ();
svc.url = "Value read from config. file or some such"
output = svc.method (input);
When you add a web reference to your project, it places the address of the web service into the .config file of your application / web application. You can then simply change this setting in the config file to point to a different web service location, assuming of course that the services are identical.
The easiest solution would be to use a software load balancer such as HAProxy. At more cost, you could use a hardware solution such as Big-IP.
Here's a hint on how to decide the URL of WSDL. I´m just changing the port but it´s of course possible to make it more advanced.
public class PortChangeReflector : SoapExtensionReflector
{
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
foreach (Service service in description.Services)
{
foreach (Port port in service.Ports)
{
foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
{
SoapAddressBinding binding = extension as SoapAddressBinding;
if (binding != null && !binding.Location.Contains("8092"))
{
binding.Location = binding.Location.Replace("92", "8092");
}
}
}
}
}
}
Put that in your Add_Code and add the following reference to your web.config.
<webServices>
<soapExtensionReflectorTypes>
<add type="Dev.PortChangeReflector,App_Code"/>
</soapExtensionReflectorTypes>
</webServices>
I hope you can get new ideas of this.
Client proxies have URL property you can set at runtime. To make it simpler, wsdl.exe utility has /appsettingurlkey key. When you generate a client proxy, it's constructor will check the key in appSettings and set the service URL accordingly. I believe WCF has this feature as well.
However, I would agree with #Matt and suggest you consider load balancing as the best solution in the long run.
Is this for scaling (each server provides the same data) or
for same API different data on each server?
For 2, then you can do as above, just change the service URL in code.
For 1, you could use round-robin DNS (e.g. you see multiple servers with at the command line type nslookup www.google.com).
I have numerous Web Services in my project that share types.
For simplicity I will demonstrate with two Web Services.
WebService1 at http://MyServer/WebService.asmx
webService2 at http://MyServer/WebService.asmx
When I generate the proxy for these two services I use:
wsdl /sharetypes http://MyServer/WebService1.asmx http://MyServer/WebService2.asmx
/appsettingurlkey:WebServiceUrl /namespace:MyNamespace /out:MyProxy.cs
The problem is that the appsettingurlkey is the same for each Web Service
in the proxy file. I want to be able to specify multiple
appsettingurlkey parameters. How is this accomplished? I figure
since the /sharetypes parameter became available, there should be a
solution for specifying the appsettingurlkey specifically for each
Web Service identified.
If this is not possible with the wsdl.exe, what would you propose I do? I would rather not update the generated code that wsdl.exe outputs and I don't want to go through my whole application passing in the Url to each instance of the Web Services.
The proxy classes generated are partial classes, so my solution would be to add your own constructor in a different (non-generated) code file, which explicitly reads a different setting for each proxy.
To suplement Elijah's own answer, here's the email answer I gave him.
I had to blog it because the XML didn't paste well into this text box: http://www.rickdoes.net/blog/archive/2008/09/29/wsdl-shared-types-and-configuration.aspx
Ahh, instead of creating another partial class with an overloaded constructor passing in the Url, the following additional parameters to the wsdl.exe will solve my problem...
wsdl /sharetypes http://MyServer/WebService1.asmx http://MyServer/WebService2.asmx /appsettingurlkey:WebServiceUrl /namespace:MyNamespace /out:MyProxy.cs /appsettingurlkey:BaseSoapUrl /appsettingbaseurl:http://MyServer/
If the web.config has a BaseSoapUrl appSetting, then it will use that to replace the http://MyServer/ sub string from the MyProxy.cs. If the appSetting is not present, then it will just use the path provided in the wsdl.exe (example: {BaseSoapUrl}/WebService1.asmx when using the appSetting or http://MyServer/WebService1.asmx when not using the appSetting).
A thanks goes out to Rick Kierner for pointing me in the right direction.