Can I modify Endpoint after it is added to the servicehost? - wcf

I am trying to figure out how to get an handle on the endpoints of the service host and modify their identity. I have endpoints defined in the config file but want to modify the endpoints programmatically depending on the environment (ex:QA, UAT, Prod)
Service is hosted on IIS6 and I am using a servicehostfactory to provide my extended servicehost class to IIS.
I am using opening event to get an handle on the endpoints that are already defined from the config file but can't figure out how to modify their identity. Is that even possible? Are endpoints are immutable after they are created?
If I can't modify the endpoints then is the "Opening" event of the servicehost is the correct event to add a service endpoint?

ServiceHosts are not immutable until they are Opened. You can modify the description of an endpoint after calling AddServiceEndpoint.
When you say Opening event, do you mean you've subclassed ServiceHost and are overriding OnOpening? If so, that's a fine place to add endpoints.
Alternatively, if you're using your own ServiceHostFactory, you can just add your endpoint(s) after calling base.CreateServiceHost.

Related

Create WCF Service to be hosted differently

I have a WCF service which programmatically creates its endpoints rather than using a config file - I'm looking into this as our field engineers are prone to break XML easily and we may use different types of binding in different scenarios.
This works well in self-hosted environments (console app, windows app) and as a Windows Service.
Can I do this with a service in IIS or do I have to provide a .SVC file for each endpoint ?
Also will the endpoint address from the client end have to include the .SVC extension ?
This is not a service intended to be used by third parties, only by our client components. We may expose parts of our API later but not initially.
If you're using .NET Framework 4.0 (and later), you can use the ASP.NET routing integration to define a service using a custom ServiceHostFactory implementation. A few things you'll need:
In web.config, set the attribute aspNetCompatibilityEnabled on the <system.serviceModel / serviceHostingEnvironment> element to true
Add a global.asax / global.asax.cs file, and in the Application_Start add a new ServiceRoute to the ASP.NET RouteTable.Routes collection. The service route requres you to define a new service host factory, where you can define your endpoints programmatically.
With that you'll be able to have endpoints without the ".svc" in their addresses. You can also use the service host factory without using routes, by creating a .svc file for each service (not endpoint), and using the Factory attribute in the <%# ServiceHost directive.
For more information about service host factories, check the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/14/wcf-extensibility-servicehostfactory.aspx.

Quick and easy implementation of a WCF web service, given wsdl?

I'm writing a client to access a SOAP webservice, that will be hosted by a third party. I have the WSDL and XSD that define the interface and the data.
I've had no problem in creating a service reference from the WSDL, but I'm having a problem in building a simple web service that implements it, that I can use to test against. (The third party's service isn't ready, yet, but even were it running, I'd still like to do my initial testing against my own test server, not against theirs.)
I've browsed around, and apparently I can use svcutil to generate an interface for the service:
svcutil.exe thewsdl.wsdl thexsd.xsd /language:c# /out:ITestService.cs
This generates a file containing the service interface definition. But now what?
I figured the easiest way to go would be to build a self-hosted service, so I created a new console app, and in it I implemented a class derived from the service interface definition, and fired it up with a ServiceHost.
It runs, and while it was running I was able to create a Service Reference in my client app. But when I try to call it, from the client app, I get an error:
The provided URI scheme 'http' is invalid; expected 'https'.
What is the easiest way to get around this? Is there a simple way to simply turn off authentication and authorization, and simply allow unrestricted access?
EDITED:
I'm adding a bounty to this, as the original question seems to have attracted no attention.
But let's get to the crux. I am trying to write a client against a customer's SOAP service. As a part of the development, I want to create my own test WCF service, that implements the same WSDL.
So I have a downloaded .wsdl file, and an associated .xsd file, and with them I want to create a service that I can test against, with VS2010's debugger.
It's not important to me whether this service runs standalone, or within IIS, or that it be production stable. All I want is a service that accepts the requests that the customer's site would accept, and return the responses to my client that I need it to return, in order to test my handling of them.
How do I get there? I've tried adding a WCF Service Library, and then using svcutil.exe within it to add my new service, but it doesn't seem to populate the app.config with the server-side boilerplate, and my attempts to reconstruct it haven't worked.
Since you want a full fledged service to call instead of mocking it.
Follow these steps:
Create new "WCF Service Application" project
Copy wsdl and xsd into project
select your wsdl file and look in the properties section and copy location from full path
Right click on the project in solution explorer and select "Add Service Reference..."
For the service address, paste the location of your wsdl that was copied in previous step and hit go. It should show the operations you are expecting for the service.
hit ok
It should generate all the objects for you including the interface and config file (although at this point is client side in the config- we will have to switch this to be the service)
Now you should add the service config section in the system.serviceModel section. Since I don't know the specifics of your wsdl what you should do is create the services node inside the system.serviceModel section and copy the endpoint node from the client node generated. For example below of services node, you can blank out the address for now:
<system.serviceModel>
<services>
<service name="YourService">
<endpoint address=""
binding="basicHttpBinding" bindingConfiguration="WeatherSoap"
contract="ServiceReference1.WeatherSoap" name="WeatherSoap" />
</service>
delete the client node in the config
In the service, it is implementing a different interface when it generated the project so you will want to replace the interface implemented with the one listed in the contract attribute in the endpoint above. Then implement its members and it should explode out the operations available. You can fill in whatever you want the service operations to return.
depending on what the wsdl has in it, we may need to do a few more things to allow the necessary bindings to run - like setting up for wsHttpbinding, netTCPbinding, etc.
I've used Moq to handle this. Basically in the unit tests you specify the interface (this would have been generated for you with adding the service reference or using svcutil) and what you want it to return if you call it.
example setup below:
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
So then when you want to moq out your service call
var myObject = new IFoo;
var resp = myObject.DoSomething("whateverwillbeoverriddenbyping");
and resp will be true.
There are other options than using Moq. The options all involve taking the interface and injecting a different version of it. For example, you could also do a constructor injection mock, by passing in the interface to your class constructor.

What is the entry method for WCF service hosted on IIS?

A little background info -
I'm trying to host a RESTful WCF service on Azure. As I understand, unless I have the ASP.NET type hosting on the role, I don't really need the global.asax class (which has the application_start method).
From basic prototyping, all I needed was the svc file and the implementation behind it and it automatically gets initialized on role startup (I mean, hosted up on IIS).This is great because I need no extra code other than web.config and my service is up and running. I don't need to create a new service host and start listening on it, etc. I'm able to deploy the role and POST messages to my service.
The problem -
I have custom logging and initialization classes implemented that I need to initialize when my service starts up. I configured my service to be a singleton and I'm not sure where I should put my custom initialization components.
Without an explicit application start method and my service configured as a singleton, can I assume that when the first request comes in, my service constructor gets called? (along with all my custom initialization?).
can I assume that when the first request comes in, my service constructor gets called?
Yes, but you should ask yourself whether you really want your service to run as a singleton. If you're happy with this then it will work fine; if you don't want it to run as a singleton then you should look into Russell's answer using a custom factory.
Look at Should WCF service typically be singleton or not? for some discussion about whether WCF services should be singletons. You need to decide for your situation, but generally WCF services are not singletons unless they need to be.
To implement a custom factory, see this MSDN link Extending Hosting Using ServiceHostFactory. As the link describes, extend the service host factory like so
public class DerivedFactory : ServiceHostFactory
{
public override ServiceHost CreateServiceHost( Type t, Uri[] baseAddresses )
{
return new ServiceHost(t, baseAddresses )
}
}
And then specify your factory in the ServiceHost directive
<% # ServiceHost
Service="MyNamespace.MyService"
Factory="MyNamespace.DerivedFactory" %>
You're looking for ServiceHostFactory. You can add a part to the SVC file to use a factory, where you can do any logging etc. you may need.
I have used this in the past to start a background worker to launch a separate thread for some background work.
http://msdn.microsoft.com/en-us/library/system.servicemodel.activation.servicehostfactory.aspx
Hope this helps you get where you need to be. :)

Create WCF endpoint configurations in the client app, in code?

I am trying to consume a WCF web service from a .NET client application, and I think I need to be able to programmatically create endpoints, but I don't know how. I think I need to do this because, when I try to run the application, I am getting the following error:
Could not find default endpoint
element that references contract
'IEmailService' 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.
While troubleshooting this error, I created a simple windows forms application, in which I try to consume the same web service. With this test application I can connect to the web service successfully, and I get a valid response. But, I can reproduce the exact error cited above within in my test app by removing the system.serviceModel node and all of its child nodes from the application's app.config file (I might not have to remove ALL of that section, I'm not sure). So, my first thought was that I need to add that section to the app.config file for the real app, and everything should be fine. Unfortunately, for ridiculous reasons that I won't get into here, that is not an option. So, I am left with having to generate this information in code, inside the client app.
I am hoping someone here can help me work through this, or can point me toward a good resource for this sort of problem.
Is it possible to create endpoint configurations in the client app, in code?
By default, when you do an Add Service Reference operation, the WCF runtime will generate the client-side proxy for you.
The simplest way to use it is to instantiate the client proxy with a constructor that takes no parameters, and just grab the info from the app.config:
YourServiceClient proxy = new YourServiceClient();
This requires the config file to have a <client> entry with your service contract - if not, you'll get the error you have.
But the client side proxy class generated by the WCF runtime also has additional constructors - one takes an endpoint address and a binding, for instance:
BasicHttpBinding binding = new BasicHttpBinding(SecurityMode.None);
EndpointAddress epa = new EndpointAddress("http://localhost:8282/basic");
YourServiceClient proxy = new YourServiceClient(binding, epa);
With this setup, no config file at all is needed - you're defining everything in code. Of course, you can also set just about any other properties of your binding and/or endpoint here in code.
An east way to consume a WCF service if you have a reference to the assembly which defines the interface, is using the System.ServiceModel.ChannelFactory class.
For example, if you would like to use BasicHttpBinding:
var emailService = ChannelFactory<IEmailService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(new Uri("http://some-uri-here.com/));
If you don't have a reference to the service assembly, then you can use one of the overloaded constructors on the generated proxy class to specify binding settings.

WCF - Dynamically calling different web service endpoints implementing the same interface

I have a number of different applications that implement the same contract. In my main app, I would like to have one proxy. Then dynamically, given a Uri for a particular application, I would create a web service request and call that. How can that be accomplished? Thanks!
Do these steps:
generate your client-side proxy based on one service
this will generate the C#/VB.NET classes for you, as well as the app.config (or web.config if your client is a web app)
when calling the default service endpoint, you can do something like:
YourServiceClient client = new YourServiceClient();
client.CallSomeMethod();
This will use all the settings from the default service endpoint as defined in your config file
if you need to provide a different endpoint, do this:
YourServiceClient client =
new YourServiceClient("default", "http://server/YourOtherService.svc");
client.CallSomeMethod();
There is an overload for the client constructor which will take two parameters: the name of the endpoint configuration in your client config file (you need to look that up after you've added the service reference), and the endpoint URL you want to connect to (which can be different from what's stored in the config).
If all the other parameters like service contract, binding information etc. stay the same, this method should work and it should allow you to connect to any number of varying endpoints using this second constructor overload.
When you instantiate the service client, you can set the uri
ReconcileSvc.ReconcileClient client = new ReconcileClient();
client.Endpoint.Address = new System.ServiceModel.EndpointAddress(uri);
Hope it helps.