I am fairly new with WCF, I'm looking to share a service contract and data contracts between service in one solution and a service consumer in another solution. I have created a seperate project which is shared between both solutions that contains both the service contracts and the data contracts. When i reference my service The data contracts are being shared but not the service contract. My contract looks like the following:
[ServiceContract]
public interface IDistributionService
{
[OperationContract]
[ServiceKnownType(typeof (Distribution))]
bool AddDistributions(Distribution[] oDistributions);
}
When I look at the reference.cs file I is using the Distribution objects but it's generating the IDistributionService contract again, here is an excerpt of the reference.cs file:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="eDistributorService.IDistributionService")]
public interface IDistributionService {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDistributionService/AddDistributions", ReplyAction="http://tempuri.org/IDistributionService/AddDistributionsResponse")]
bool AddDistributions(mhcb.syd.eDistribution.WebServices.Contracts.DTO.Distribution[] oDistributions);
}
Is there any way of getting the consumer to use the IDistributionService interface without generating the concrete instance in the reference.cs file?
The main reason I want to know is so that I can use dependency injection (unity).
.RegisterType<IDistributionService, DistributionServiceClient>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior(container.Resolve<IInterceptionBehavior>()))
Thanks again!
Firstly check that you are instructing the service reference tool to 'reuse types'. When you go to 'Add Service Reference...', click 'Advanced' and confirm that the 'Reuse types in referenced assemblies' option is checked.
If this is checked (which I believe is the default behaviour), then you might not be able to do what you want by adding adding a 'service reference'.
Sharing a contract is the preferred WCF pattern (in my opinion), but the implementation I normally take is to use the ChannelFactory class to instantiate the client connection rather than use the generated proxy. The generated proxy is fine - it's quick and easy - but it is clunky and requires maintenance.
Review this MSDN link on Using ChannelFactory vs Proxies in WCF for a discussion, and this CodeProject link for sample usage.
The code artefacts svcutil produces suck. But they are by far the easiest (i.e. cheapest) way to use the decoupling that WCF provides. Reusing contracts and entities is tight coupling of service and consumer.
If you want your container to generate client-side proxies for WCF services you can use an extension for Unity that does the trick. It supports the WCF4 discovery features as well.
Related
I am having problems in working with the Namespaces in the WCF. I have never done it before. I have tried a lot to find solution on the google. But still I am not able to find a solution for it.
I have written a WCF service which is divided in 3 projects and additionally i have created a models project:
Contracts (ServiceContract)
Service (Codebehind)
Host (ServiceHost)
Models (DataContract classes)
When I am hosting the service in IIS, it is generating the WSDL fine but there are namespaces which I have not defined as below:
http://schemas.microsoft.com/2003/10/Serialization/
http://schemas.datacontract.org/2004/07/My.Models
The problem is that I want to access all my service contracts and data contracts through same namespace only.
Because when the DataContract classes are generated in the proxy class, it is being duplicated. Mean if I have a class ClassA in my Models projects, then it is giving me 2 classes as ClassA and ClassA1.
I saw that in proxy class that these are there in the different namespace. So, I want to avoid that.
I also want to avoid ChannelFactory method, because there are a lot of OperationContract functions. So, don't want to code that much with hand but would like it to be auto generated in right fashion.
Any help is greatly appreciated. Thanks in advance.
I also want to avoid ChannelFactory method, because there are a lot of
OperationContract functions. So, don't want to code that much with
hand but would like it to be auto generated in right fashion.
This makes no sense at all. The ChannelFactory<T>.CreateInstance() method is much lighter than a wsdl-generated service proxy, and the amount of code you will have to write is comparible.
Service references are designed for when you're calling third party services which you have no control over or internal visability of.
There is aboslutely no situation I can think of where using a generated service reference is preferable to using ChannelFactory if you have access to the service definition assemblies.
This is especially the case for your requirement to manipulate the service wsdl in order to control code generation on the client side.
I have tried googling for an answer since last week and haven't found anything. Maybe I'm just searching with incorrect key words...
Basically, we have a running WCF service and then we have a separate dll with another ServiceContract in it. We want to know if it is possible to expose the separate dll in the current running service and if one can, how?
We are still new to WCF, so please excuse if this is a stupid question. :(
We are working with .NET 3.5 SP1 and C#.
Regards
EDIT:
We want to separate our service into "modules". So the service implementations (Methods, ect) and contracts (Interfaces) are all in separate libraries. So lets say you have a module called "Clients". We want everything related to Clients to be in the same separate library (DLL) instead of one big base class that inherits from multiple interfaces. This is a huge service and we need multiple developers to work on different sections of the same service at the same time. This is what I've been instructed to figure out, but if it can be done then it can't. I hope this makes more sens??
Assuming you are asking how you can implement a service contract declared in one DLL in a service running in a separate DLL/Application:
Edits to match post edits
add a reference to the DLL with the service contract to the application containing the service
In the .cs file with service implmentation add a using statement for the namespace of the service contract
derive the service from the service contract (you will have problems if you define your service contracts as concrete classes rather than interfaces and you want to expose multiple contracts on your service
If self hosting then create a ServiceHost passing the type object of the service in the other assembly, if IIS hosting create an .svc file referencing the class in the other assembly as the service
Add a service element in the config file naming the fully qualified name of the service
Add an endpoint to the service at a unique address for the new contract
When you take the other assembly (dll) as a reference in the "main" project, then add a using directive to the file where the WCF service is instantiated. Then you can simply use the referenced service contract to set up a running service with the right endpoints and binding(configuration).
I guess one work around is you have a main ServiceHost hosting your WCFMainLib and then all your clients will connect to WCFMainLib.
WCFMainLib then acts like a proxy to connect to all other WCFModuleLib on localhost (or other servers) to fetch data.
WCFMainlib will implement the IWCFModuleLib1, IWCFModuleLib2 etc service contract interfaces and expose them to the WCFClient. Actual implementation of interfaces will then be a call to the actual WCFModuleLibs.
This may introduce some overhead, but overall also introduces several "features" that may benefit your boss or service availability.
OR, if you are just wanting to delegate programming work, maybe you can tell each team to work with partial classes for your WCFLib with each service contract on a partial class then do a nightly compile.
My first question so hope it is suitable:
Shared interface assembly - I have a 'shared' assembly which has an interface, let's call it IDocRepository. It's marked with [ServiceContract] and there are several [OperationContract]-marked methods.
WCF implementation assemblies - I have two WCF service projects, each referencing the shared assembly, each implementing that interface as a WCF service.
Consumer assembly - Finally, I have a 'client' project, also referencing the shared assembly, with a reference to each of the two WCF services.
However, the service references generated in the consumer assembly derive from an auto-generated version of the interface:
public partial class ExampleClient : System.ServiceModel.ClientBase<SomeNamespace.ExampleSvcRef.IDocRepository>, SomeNamespace.ExampleSvcRef.IDocRepository {
What I expected
I would have hoped that both references would instead automatically inherit the interface I defined, that the consumer/client assembly is also referencing. Kind of like the re-use of classes that it provides for parameter and return types, but for the service interface.
Why
So that I can create an instance of either service reference proxy and cast it to my interface type.
So I could modify the generated code by hand each time, but there should be better way...?
(edit: I do have 'Reuse types in referenced assemblies' and 'Reuse types in all referenced assemblies' options selected for both service references)
"Reuse types in referenced assemblies" only allows you to reuse Data Contracts, not Service Contracts. If you want to share Service Contracts, you don't need to use "Add Service Reference" at all. You can just use ChannelFactory directly.
// Supply the binding and address in code
Binding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://tempuri.org/address");
IServiceContract channel = ChannelFactory<IServiceContract>.CreateChannel(binding, address);
// Or read them from the config file
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>();
IServiceContract channel = channelFactory.CreateChannel();
The channel object will also implement ICommunicationObject, so you can cast it if you need to call methods like Open() or Close().
Visual Studio does not support reusing you existing interface when generating the proxy classes for you. Reuse types will not reuse the contract interface as Quartermeister pointed out.
We have solved it with inheritance. Quite similar to the partial class idea above suggested by Jester Software.
This is how we solved it:
In the project of your client just create a service reference as you would have done. Then add a class that serves as the replacement for the client:
internal class MyServiceProxy : MyServiceClient, MyLogicNamespace.IMyService
{}
This class inherits from the generated MyServiceClient but states that that client does implement the original interface.
(I suggest you put them in a folder named "ServiceProxies")
If the MyServiceClient class contains any methods that do not match with the original interface then you can add them in that proxy and do the conversion in code.
After this, just use the MyServiceProxy where you would have used MyServiceClient.
When you create the service reference, there is a box you can tick to make it reuse the shared definitions. Make sure the client project is already referencing the shared assembly, add the service reference again, and check all the options carefully.
If it still doesn't work, check the binding you use. I have a vague recollection that basic HTTP binding won't support re-using of types?
There is another good option, if you want to continue to use the proxy generator for it's limited-but-somewhat-useful functionality... Use a partial class:
namespace <same namespace as generated proxy>
{
public partial class MyClient : <namespace of "real" service contract>.IServiceContract
{
}
}
Ensure that the proxy is generating code the same way your Service Contract is defining it, ie, if it's using 'List', use that option in Configure Service References as well. In other words, make sure your generated Service Interface is exactly equal to your real Service Interface and the above code should work, and to update the reference you use right-click instead of writing code.
We have lots of WCF services that are only used by our own code; the code that uses them is mostly in the same solutions files that contains the services.
However they do not use a shared assembly for the contracts, so each time a data contract is change the reference to the service has to be updated by hand in all projects that use the service. (Then the code needs to be fixed up by hand)
So how do I do a simple refactoring like renamed a data item in a data contract?
Is there a way to update all references to services in a single solution with one command, rather then having to click on each reference in each project?
You may have already answered you own question here.
Move your data contracts to a shared "Contracts" project, which will allow you to use the built in Refactor -> Rename option in Visual Studio to change the name, with the change being reflected in all of the projects in the solution.
Update
To clarify, the Contracts project is an internal "organisation" of your contracts. It allows many of your projects to reference one set of contracts. For example...
WCF service exposes "List GetCustomerById(int id)".
WCF service may call down to a processing layer, which might need to calculate something using another project etc. All of thes projects can use the single "Customer" definition from your Contracts project.
Any consumer of the WCF service would get the definition of the Customer via the service reference. You wouldn't share your Contracts project or send the dll for their use.
With your current settings you can't do it because you are regenerating the proxy each time. This is good from SOA perspective as data contract should not change very often. But if you are controlling both client and service and it is all .Net you can do as Shonee suggested. Use the /r option in svcutil to generate the proxy from the common assembly. Then you can refactor easily.
In C# (other .Net OOP languages as well), I have 2 webservices. Svc1 returns a complex datatype which becomes the parameter for svc2. Note that it is the same complex type.
Now, I create the 2 proxy classes of these 2 webservices. Which means the same type gets generated twice.
How can I make sure that in 2 proxies only one copy of that type is there? You may assume same or different namespaces of 2 webservices.
Generate the two proxies at the same time:
svcutil http://example.com/svc1?wsdl http://example.com/svc2?wsdl
If the type is really the same (name and namespace) in both services it will generate only a single proxy class for the client.
Yet another possibility is to generate the proxy class for the first service:
svcutil http://example.com/svc1?wsdl
compile the generated .cs file into an assembly for example MyAssembly.dll and use the /reference option when importing the second service:
svcutil /reference:MyAssembly.dll http://example.com/svc2?wsdl
This will look for same types in the WSDL and the supplied assembly.
I've run into a similar issue recently; I haven't tried Darin's advice.
Miguel Castro of IDesign gave a great presentation on "WCF the Manual Way… the Right Way" at the March 2009 DevConnections. In that he showed how to reuse service contracts and proxies. From my notes:
One assembly for Service/Data Contracts
Shared between client & server
One assembly for services
Permits changing host and reusing
One assembly for proxies
Reuse among clients
Separate application for hosting
Do not use "Add Service Reference"
Service (POCO) project references Contracts (interfaces) project and System.ServiceModel
Client Proxies assemblies reference Contracts assembly but not Service project
Client applications instantiate proxies
Our company hasn't made the move to WCF yet, but this looks like the way to go (to me).
EDIT: I found an article by Mr. Castro on this.