I am currently developing a WCF client to interaction with a set of WCF service references. I am developing in c#.
I don't want to following the approach of having to generate a service reference using svc util or manually adding a service reference to my class library.
Have I an other alternatives open to me? I am considering using the ServiceClient class within the ServiceModel library.
I am little confused though, for example the request and response objects related to an endpoint, where are these created or how are they created? In a previous project I used T4 mappings and DTO's, but I feel these are over kill. I did like though that I could share the same object between different service endpoints. My goal here is to create a custom client object communicating through a custom written proxy. I would like some direction on this.
To talk to a WCF service (endpoint) you need to know three things (ABC): the address of the endpoint, the binding it uses, and the contract used in the communication. If you have all those three things, you don't need to use any tool to interact with the service.
The address is just the URI of the endpoint. The binding is represented by one instance of the abstract System.ServiceModel.Channels.Binding class (such as System.ServiceModel.BasicHttpBinding, System.ServiceModel.WSHttpBinding and so on). And the contract is usually represented by an interface decorated with the [ServiceContract] attribute. If you have all those three, you can create a custom proxy by using the ChannelFactory<T> class, as shown below.
public static void TalkToService(Binding binding, Uri endpointAddress) {
// Assuming that the service contract interface is represented by ICalculator
var factory = new ChannelFactory<ICalculator>(binding, new EndpointAddress(endpointAddress));
ICalculator proxy = factory.CreateChannel();
Console.WriteLine(proxy.Multiply(45, 56));
}
Related
Background:
I have to extend an application which already uses WCF services with another WCF Service. One of these already existing services should call the new WCF service. Now the requirements are that the future service should be mocked and the connection between this two services should be tested (not a unit test) with this mock service before implementing the real service. The mock service should write the received parameters to a file.
Goal:
This means the endpoint in the existing WCF service is implemented and ready (except for some changes in the config).
My approaches:
Implement own mock service (Blog post) or use a mock framework (WCFMock) which mocks a already defined interface.
Problems:
The call of the mock service looks different and I have to change the code of the endpoint after the implementation of the real service.
My Question:
Is it possible to mock or fake a WCF service (without real web call) and implement the endpoint which will also work with the real WCF service after changing the config?
Yes. You will need to create a class that acts as an intermediary for the WCF service client calls and then either loads an actual client or your mock service depending on some value (probably a config value). This way, the dependencies in your code are handled such that all you need to do is change a flag in order to switch implementations.
The biggest constraint on this working is that the service interface must be available to the client to implement.
Basic idea is as follows:
public class ServiceFacade : IMyWCFService
{
private IMyWCFService _clientImplementation;
public ServiceFacade()
{
_clientImplementation = (Settings.Default.UseMockService == true) ? new MockWCFServiceClient() : new MyWcfServiceClient();
}
#region IMyWCFService implementation
public int MyServiceCall()
{
return _clientImplementation.MyServiceCall();
}
#endregion
}
I am writing a basic WPF GUI to connect to a WCF service and consume an interface. So far I have connected to the test system by creating a service reference, putting in the URI for the test service I want to consume, it finds the interface and creates the proxy via service reference for me.
What I want this to do when you run the GUI app is for the user to be able to pick an environment - development, test or production and for the GUI to then connect to the appropriate WCF service depending on the environment selected.
How can I do this?
You can overwrite the Endpoint like this:
client.Endpoint.Address = new EndpointAddress(GetAddressForCurrentMode())
The other way you could to it, is to write a method, maybe an extension method, that accepts the service contract and the implementation class. Further more it either accepts a configuration name, or an endpoint:
public static TClient GetServiceClient<TClient, TContract>(string endpoint)
where TClient : ClientBase<TContract>
{
// Construct client
}
To construct the client, use one of BaseClient<T> overloads (from MSDN).
To then consume the client, just use the method above as normal:
using(var client = ServiceInterop.
GetServiceClient<MyClient, IMyContract>("http://foo.bar"))
{
// Consume client
}
The ONLY argument I can see for SOAP WCF over REST (json) wcf is the fact that once my service is created I can add a a reference in visual studio and I get a load of strongly typed classes ready for me and a client class that I can call all my webmethod through. It even sets up the web.config as far as I remember.
However when I expose a REST (json) service I still get a WSDL. So Im wondering is there still a way to build my references automatically?
Not using WCF tools. Unlike with SOAP (which has an established protocol for describing services - WSDL), REST doesn't. WADL is one such protocol, but it isn't too widespread and WCF does not support it. You still get a WSDL, because WCF will describe everything it can from the service. However, the WSDL won't have a <wsdl:port> element, which would describe the REST endpoint, which is why you get the WSDL, but cannot generate a reference to it.
The post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx has a lot more info on this issue.
Very old question, newer answer.
today using openapi (swagger) I can achieve this by using swagger inspector doing samples i can document my rest services as well as create a spec yml/json file allowing for validations and acceptance criteria as well as automated clients for java,python,c#,ruby,javascript and others I'm sure
I would like top elaborate:
Although it is true you cannot get a WSDL add service reference with a JSON REST WCF service, what I do is create two met data hooks:
is the operations returning JSON
is a single XML op returning a class wrapper which includes all the service classes I allow, I call it Discover:
i.e.
public class Discover
{
public Manager Manager {get;}
public Employee Emp {get;}
....
}
[OperationContract]
public Discover DiscoverDTOs()
You can, indirectly. While the client generated by Visual Studio won't work, that client implements an interface, also generated, that you can use like this:
WebChannelFactory<IService> factory = new WebChannelFactory<IService>(new Uri(endpointAddress));
IService proxy = factory.CreateChannel();
int result = proxy.Operation(1, 2, 3);
WebChannelFactory has another overload which accepts a WebHttpBinding, you can configure based on the service configuration, or you can make this configuration manually in your app.config file.
Trying to send a complex type between two systems that have the same code base. They are both aware of the same object that is the data transport medium. However when I pass object on the consumer proxy it appears as an object in the web service namespace instead of the one in the application.
Is there anyway that I can define to use the internal object?
[WebMethod]
public void Run(TransportObject transport)
appears in my application under MyNamespace.Webservice.Transport instead of MyNamespace.Objects
As Henk says sharing of types in WCF is default behavior.
I will qualify that by expanding on it and demonstrating how to achieve it:
So rather than have visual studio generate a service reference for you, you can have WCF create the proxy when it executes by using ChannelFactory.
For example:
// Create service proxy on the fly
var factory = new ChannelFactory<IMyServiceContract>("NameOfMyClientEndpointInConfigFile");
var proxy = factory.CreateChannel();
// Create data contract
var requestDataContract = new MyRequestType();
// Call service operation.
MyResponseType responseDataContract = proxy.MyServiceOperation(requestDataContract);
In the above example, IMyServiceContract is your service contract, and MyRequestType and MyResponseType are your data contracts, which you can use by referencing the assembly which the service also references (which defines these types).
[WebMethod] implies it's an ASMX based service, not a WCF service...
Try again with an [OperationContract] in a [ServiceContract]
Sharing of Types in WCF is possible, I think it's even the default behaviour.
I am currently refactoring a large WCF service which consisted of one service contract interface ("SCI" from here on) used by multiple different client applications. I have split up the SCI so that for each type of client application there is an SCI specific to the operations it requires. Some shared sections of the SCI's are defined in a base SCI, which the client application specific SCI's inherit.
There is a single service class that implements all the client specific SCI's. The fact that there is a diamond interface inheritance situation from the shared base SCI means, sometimes, that the same operation is available through multiple SCI's. When auto-generating clients (especially with async client methods), the resultant code has many ugly <generated-type>1,2,3 etc...
In order to avoid this, I would like to add a service reference to each of the client applications that only generates a client for the SCI relevant to that particular application. This should result in no problems due to the same function appearing on different SCI's.
Is this possible?
Any other tips on achieving both modularity and code-reuse in this situation would also be appreciated.
What you want to do is to create a service contract interface (you can manually do this, pull it from the original service implementation or auto generate it then copy it out).
Then instead of using a service reference use the channel factory to bind to your service (as below). This is a way nicer way of referencing WCF services.
You need the following refs to do this:
using System.ServiceModel;
using System.ServiceModel.Description;
Then you can use the following:
var binding = new WebHttpBinding();
var factory = new ChannelFactory<IMyServiceContract>(binding, new EndpointAddress("http://url:port"));
factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
var myService = factory.CreateChannel();
myService.ServiceMethod();
Luke's suggestion worth to try. The 'ChannelFactory' way has many advantages then the auto-generating way: you can keep the comments of your SCi, and no need to update reference after SCI changes.
In production, you may need to do some Singleton chache for performance, and separate SCI for Service implementation, so you can reference your SCI both in client and Service implementation.
You have mentioned 'async', I think this may be a Binding or Behavior configuration issuse.
private ChannelFactory CreateFactoryInstance<T>(string endpointConfigurationName, string endpointAddress)
{
ChannelFactory factory = null;
factory = new ChannelFactory<T>(endpointConfigurationName, new EndpointAddress(endpointAddress));
factory.Open();
return factory;
}