Has any one ever implemented a custom serializer in WCF ? The reason i want to replace the WCF default serializer with custom serializer is to call different services from the same wcf proxy client.I would be glad if some one can suggest a way to do this ?
I did something similar on a project I recently did.
However I did have 2 different WCF clients. How I "switched" was I then created a shared interface between the clients and then used a ServiceLocator to fetch the IClient.
Does this make sense?
If I understand the problem correctly you have an application that you want to talk to one of two services that use the same interface based on some criteria. The services have different configurations so you cannot reuse the same config.
To tackle this I would setup the two configurations in the application config, it could also be done in code if you wish.
<client>
<endpoint address="http://service1"
binding="basicHttpBinding"
bindingConfiguration="Service1Binding"
behaviorConfiguration="Service1Behavior"
contract="IServiceInterface, Service"
name="Service1"/>
<endpoint address="http://service2"
binding="basicHttpBinding"
bindingConfiguration="Service2Binding"
behaviorConfiguration="Service2Behavior"
contract="IServiceInterface, Service"
name="Service2"/>
</client>
In your code you then need some sort of conditional statement to determine which service you want to talk to. Once you have done this you can create a ChannelFactory for the required configuration.
string serviceName = FullMoon ? "Service1" : "Service2";
var channelFactory = new ChannelFactory<IServiceInterface>(serviceName);
var proxy = channelFactory.CreateChannel();
proxy.SomeServiceCall();
channelFactory.Close();
If you are using IoC to inject the proxy you will probably need to push this into some sort of factory. You can also look at optimizing this as creating the ChannelFactory is the expensive part, it is possible to create the Factory without specifying the configuration just the contract. You would then need to specify the binding and the endpoint when you create the channel.
Related
first of all this is not duplicate. I have a little bit different question.
Is it good practice to get rid of WCF's config in App.config file in the client (or clients in case of cross-platform project) and replace it with injected Proxy class (from different dll, shared for all clients)?
I'm just starting so my config file is not big, but here is an example:
App.config (WCF part):
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8002/MyService"
binding="netTcpBinding"
contract="CallbackExample.Client.IMyService" />
</client>
</system.serviceModel>
I must have this code copy and pasted into every client I made. Working with Xamarin I can have many clients written in C# in single VS solution. So I though, why not just get rid of system.serviceModel section and do that:
MyServiceProxy.cs:
public class MyServiceProxy : ClientBase<IMyService>, IMyService
{
public MyServiceProxy()
: base(new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:8002/MyService"))
{
}
public int JustAMethod()
{
return Channel.JustAMethod();
}
}
This way, I will have my configuration in single place.
So, my question is: Is it considered as a good practice? Is there a better way? I'm not sure, cause WCF is all about flexibility and easy config through App.config flie.
If there is no need for additional configuration, I always go for pure code solutions.
Back in the day WCF was slightly more complex to configure, via app.conf. With the ServiceHost you can even configure a WCF service in pure code.
The same applies to a WCF client imo; if you don't have the need to configure it via a config file for your users: I'd say go for the pure code solution.
Here another discussion of the same topic. (kind of the same reasoning, the question remains; do you need the configuration flexibility).
One potential downside to doing everything in code is that you lose the flexibility to configure not just the endpoint, but also the binding, without recompiling and redeploying. The binding includes some important network-related attributes (timeouts, transport protection levels, authorization schemes, etc) that you may want to tweak depending on the environment in which some of your client programs can run.
Note that you don't necessarily have to have a separate *.exe.config file for every client application. You can have a common .config file that each application can load explicitly. See ConfigurationManager.OpenMappedExeConfiguration
We've used the solution in this old topic ("WCF Service Reference generates its own contract interface, won't reuse mine"), but that only solves the problem of reusing interfaces. What we would like to do, if possible, is to also retain the use of config files to setup and configure various options on WCF client side using all the bells and whistles of <system.serviceModel> node.
The approach that was given forces us to do all that in code, and that already proved to be a problem at one point (we had to change a binding configuration parameter which forced us to go through an entire corporate change request approval process to alter two lines in the code base, which is a huge hassle compared to a request to change config file).
Is there a solution that combines these two worlds?
Lets say you have IService as your service contract and it is shared between the client and the server.
Then in client code you would have something like this:
ChannelFactory<IService> factory = new ChannelFactory<IService>("ServiceClient");
var channel = factory.CreateChannel();
var result = channel.GetData(1);
In Client app.cofnig you would have a section that looks like this:
<system.serviceModel>
<client>
<endpoint name="ServiceClient" address="http://localhost:51377/service.svc" binding="basicHttpBinding"
contract="Common.IService"/>
</client>
</system.serviceModel>
Briefly explained ChannelFactory creates Channel to access IService service using ServiceClient endpoint configuration in app.config.
You can expand serviceModel configuration as you wish. Just add additional code to properly close channel once operation is complete.
What exactly is it that you're trying to achieve? Seems like you're trying to reuse contracts, but have SVCUTIL/VS generate the ClientBase<T>-derived class and modify the .config file?
If so, I don't think that's a supported scenario, really. Honestly, if you need to reuse your service contract interfaces, you might as well implement the ClientBase<T>-based proxy class by hand. It's only a little bit of additional work, and will make your life easier in the long run.
There isn't a supported option in SVCUTIL/VS to only import the binding configuration rather than the entire thing, though, so you'd likely need to write your config file by hand as well (or copy it from a manual run of SVCUTIL).
I'm working on a web application using mvc, we have already a service that does http binding, the client wants tcp binding for certain actions (not really sure why) but it's their requirement so i'm attempting to set up net.tcp binding, all references i am seeing to doing this involve a windows application and not a web application.
I guess my question has 2 parts, first can you run httpbinding and net.tcp binding at the same time through the same service/project.
secondly how would I consume the service through a webproject?
From "Programming WCF Services"
http://www.amazon.de/Programming-WCF-Services-Mastering-AppFabric-ebook/dp/B0043D2DUK/ref=sr_1_fkmr0_1?ie=UTF8&qid=1408811647&sr=8-1-fkmr0&keywords=programming+wcf+services+3d+edition
Every service is associated with an address that defines where the service is, a binding
that defines how to communicate with the service, and a contract that defines what the
service does. This triumvirate governing the service is easy to remember as the ABC of
the service. WCF formalizes this relationship in the form of an endpoint. The endpoint
is the fusion of the address, contract, and binding.
So, in your case you'll need to define 2 endpoints for your service.
Example from the same book:
<service name = "MyService">
<endpoint
address = "http://localhost:8000/MyService"
binding = "wsHttpBinding"
contract = "IMyContract"
/>
<endpoint
address = "net.tcp://localhost:8001/MyService"
binding = "netTcpBinding"
contract = "IMyContract"
/>
<endpoint
address = "net.tcp://localhost:8002/MyService"
binding = "netTcpBinding"
contract = "IMyOtherContract"
/>
</service>
On the client side you'll need to "Add service reference" in VS and provide an address of the desired endpoint.
http://msdn.microsoft.com/en-us/library/bb628652.aspx
1) Yes, you can set up both HTTP and a net.tcp endpoints (each of which will require it's own metadata exchange endpoints) within a service. More details here.
2) In your web application project, right click on References then click on Add Service Reference. In the dialog, copy the endpoint address of the net.tcp service. Enter the desired namespace and click ok.
I am working on a task where I have to list the number of applications calling our web/wcf services.
Currently I am looking into the applications folders structure, and looking for the folder "Web References" to list all web services.
But this way of finding the total list for WCF services does not work because WCF services can be consumed in many other ways.
Is there a foolproof way of doing this?
One of ways would be implementing your own message inspector on server, deriving from
IDispatchMessageInspector, and logging IP address of every request
(see example here).
If you need more detailed information, for example, if there are multiple clients
on one machine - you need to include client identification into your contract,
and send it either in custom headers, or implement authentication.
But of course, this does not prevent multiple clients from using same identity.
You can add custom headers to client configuration.
<endpoint address="http://localhost:8080"
binding="basicHttpBinding"
contract="CalService.ICalService">
<headers>
<ClientIdentification>Cal1</ClientIdentification>
</headers>
</endpoint>
And retrive that using following code
var operationContext = OperationContext.Current;
var requestContext = operationContext .RequestContext;
var headers = requestContext.RequestMessage.Headers;
int headerIndex = headers.FindHeader("ClientIdentification", "");
var clientHeaderString = headers.GetHeader<string>(headerIndex);
see this also.
I am building an single application that uses WCF to call out to multiple external endpoints. All of the remote endpoints are identical except for the URI. I would like to treat them as a pool: add and remove endpoints through configuration and have the application understand what to do.
My original plan was to define one endoint in the app.config, then iterate over my list of endpoints and update client.Endpoint.Address on the fly to point to the right place. Unfortunately, that property is read-only, rendering that plan unworkable.
I'm a little bit stumped here. Any suggestions on how I might accomplish this?
How to: Create a Service Endpoint in Code shows you how to manage service endpoints in code rather than configuration.
Have you tried a separate name that is passed in to the client constructor?
<endpoint address="http://localhost:18000/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="BasicHttpBinding_IMyService" />
<endpoint address="http://localhost:18001/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="MyService_Secondary" />
<endpoint address="http://localhost:18002/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="MyService_Tertiary" />
Store the end point addresses in a DB table and use Jason's suggestion for creating end points in code. When a new endpoint shows up you just add another row to the table and force the service to re-query the endpoint table.
How to: Create a Service Endpoint in Code
http://msdn.microsoft.com/en-us/library/ms731080.aspx