I have multiple DataContracts and the same number of WCF Services to manage methods for each one. I have a specific [DataContract] called User that I use as paramenter in every other service, for example: ListCompany(User, CompanyId).
When a make a service referece to the WCF service, Company, it has a [DataContract] User too like Company.User which is different from the original User. Is there any way to solve this?
Logically Same DataContract, Used in Multiple Services
You are probably adding service references in the usual way for a WCF service client using the Add Service Reference... menu option. When you do that, a Reference.cs file will be generated for each service, and each service will have a different namespace. However, since you're sharing contracts across services, you need to click the Advanced... button on the Add Service Reference dialog and make sure the Reuse types in referenced assemblies is checked and (easiest) make sure Reuse types in all referenced assemblies is checked.
Now, that will not work if you don't actually have normal project or assembly references to the assemblies that contain those [DataContract] classes. So, add those references. If those classes are mixed into your server-side implementation, you will need to move them to their own assemblies and reference them on both the client and server.
Logically Different DataContract, Used in Multilpe Services
If you really have two different types of users (i.e. two different contracts) where you are using one contract for one service client and one contract for another service client, you should make sure Reuse types in referenced assemblies is not checked, and make sure that each service reference is in a different namespace.
An alternative is using a different name for each when declaring them:
[DataContract(Name = "User"]
public class User { ... }
[DataContract(Name = "CompanyUser")]
public class User { .... }
The code above assumes each User class is in a different server-side namespace, possibly different assembly as well.
I would suggest that you should look into a better way to use your WCF services that adding service references. This golden article describes how you can share the data contracts between all your solutions, and make use of them by using Chanel factories, without having VS generate loads of code for you. http://www.netfxharmonics.com/2008/11/understanding-wcf-services-in-silverlight-2
It might seem like a lot to take in, but it's full of really useful tips, including Service Access without magic which goes like this:
Now we may turn our attention to the client application. To begin,
let me start off by reminding everyone that you shouldn't ever use
"Add Service Reference" in Visual Studio for magical service client
creation. The code is incredibly verbose, hard to manageable, edits
are prone to being overwritten, and it's almost always used as an
excuse to not actually learn WCF. There are few things worse than
having to deal with people who thing they know a product simply
because they know how to use a mouse. There are reasons why Juval
Lowy, in all his books and talks, repeatedly tells people to avoid
using this flawed feature. Fortunately, as professionals, we have the
ability to understand how to do things without magic.
As I've mentioned many times already, WCF relies on the concept of the
ABC. We've seen how we configure a WCF host by creating an endpoint
specifying an address, binding and contract. As it turns out, this is
all that's required on the client side as well. For both .NET and
Silverlight, you merge an address and a binding with a contract in a
channel factory to create a channel. This isn't just fancy conceptual
architect speak, this is exactly what your code would look like (the
sign of really good architecture!) Below is the .NET version of what
I mean:
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
Well worth a read.
Related
I have a set of services I want to be able to access via one end point altogether.
Now I want to build something in wcf rather than use an existing framework/software so that is out of the question.
Suppose I have 10 contracts each representing a contract of an indepedent service that I want to "route" to, what direction should I go?
public partial class ServiceBus : ICardsService
{
//Proxy
CMSClient cards = new CMSClient();
public int methodExample()
{
return cards.methodExample();
}
So far I've tried using a partial class "ServiceBus" that implements each contract but then I have more than a few (60+) recurrences of identical function signatures so I think I should think in a different angle.
Anyone got an idea of what I should do? or what direction to research? currently I'm trying to use a normal wcf service that's going to be configured with a lot of client end points directing to each of the services it routes TO - and one endpoint for the 'application' to consume.
I'm rather new at wcf so anything that may seem too trivial to mention please do mention it anyway.
Thanks in advance.
I have a set of services I want to be able to access via one end point
altogether.
...
So far I've tried using a partial class "ServiceBus" that implements
each contract
It's questionable whether this kind of "service aggregation" pattern should be achieved by condensing multiple endpoints into an uber facade endpoint. Even when implemented well, this will still result in a brittle single failure point in your solution.
Suppose I have 10 contracts each representing a contract of an
indepedent service that I want to "route" to, what direction should I
go?
Stated broadly, your aim seems to be to decouple the caller and service so that the caller makes a call and based on the call context the call is routed the relevant services.
One approach would be to do this call mediation on the client side. This is an unusual approach but would involve creating a "service bus" assembly containing the capability to dynamically call a service at run-time, based on some kind of configurable metadata.
The client code would consume the assembly in-process, and at run-time call into the assembly, which would then make a call to the metadata store, retrieving the contract, binding, and address information for the relevant service, construct a WCF channel, and return it to the client. The client can then happily make calls against the channel and dispose it when finished.
An alternative is to do the call mediation remotely and luckily WCF does provide a routing service for this kind of thing. This allows you to achieve the service aggregation pattern you are proposing, but in a way which is fully configurable so your overall solution will be less brittle. You will still have a single failure point however, unless you load balance the router service.
I'm not sure about making it client side as I can't access some of the
applications (external apis) that are connecting to our service
Well, any solution you choose will likely involve some consumer rewrite - this is almost unavoidable.
I need to make it simple for the programmers using our api
This does not rule out a client side library approach. In fact in some ways this will make it really easy for the developers, all they will need to do is grab a nuget package, wire it up and start calling it. However I agree it's an unusual approach and would also generate a lot of work for you.
I want to implement the aggregation service with one endpoint for a
few contracts
Then you need to find a way to avoid having to implment multiple duplicate (or redundant) service operations in a single service implementation.
The simplest way would probably be to define a completely new service contract which exposes only those operations distinct to each of the services, and additionally a single instance of each of the redundant operations. Then you would need to have some internal routing logic to call the backing service operations depending on what the caller wanted to do. On second thoughts not so simple I think.
Do you have any examples of a distinct service operation and a redundant one?
I'm designing a new solution that will consist of three projects:
"Server" - a WCF service
"Client" - a winforms app that will call the WCF service
"ServiceContract" - a class lib containing some base classes plus the WCF service contract (interface). This will obviously be referenced by the Server, and also by the Client (I'm using a ChannelFactory rather than have VS generate a service reference). The service contract looks something like this:-
[ServiceContract]
[ServiceKnownType("GetCommandTypes", typeof(CommandTypesProvider))]
public interface INuService
{
[OperationContract]
bool ExecuteCommand(CommandBase command);
}
It's a very basic operation - the client creates a "command" object and sends it to the server to be executed. There will be many different commands, all inheriting from CommandBase (this base class resides in the "ServiceContract" project). As I'm using the base class in the WCF operation signature, I have to specify the known types which I'm doing dynamically using the ServiceKnownType attribute. This references a helper class (CommandTypesProvider) that returns all types deriving from CommandBase.
I've created a simple proof of concept with a couple of derived command classes that reside in the "ServiceContract" project. The helper class therefore only has to reflect types in the executing assembly. This all works fine.
Now in my "real" solution these command classes will be in different projects. These projects will reference the ServiceContract project, rather than vice-versa, which makes it difficult (or impossible?) for the helper to reflect the "command" assemblies. So my question is, how can I provide the known types?
Options I've thought about:-
The "Server" and "Client" projects will reference both the "ServiceContract" project and the various "command" projects. My helper could reflect through AppDomain.CurrentDomain.GetAssemblies(), but this fails because the "command" assemblies are not all loaded (I could force this by referencing a type in each, but that doesn't feel right - I want it to be a dynamic, pluggable architecture, and not have to modify code whenever I add a new command project).
Specify the known types in config. Again it would be nice if the app was dynamic, rather than have to update the config each time I add a command class.
Is there any way to access the underlying DataContractSerializer on both the client and server, and pass it the known types? I guess I'll still have the same issue of not being able to reflect the assemblies unless they've been loaded.
Refactor things to enable the ServiceContract project to reference the various command projects. I can then reflect them using 'Assembly.GetReferencedAssemblies()'. I guess the various command classes are part of the service contract, so perhaps this is the way to go? Edit: looks like this has the same problem of only finding loaded assemblies.
Any ideas greatly appreciated! Is it something that can be achieved or do I need to rethink my architecture?!
Thanks in advance.
One thing to consider is using the DataContractResolver.
Few resources:
WCF Extensibility – Data Contract Resolver by Carlos
Building Extensible WCF Service Interfaces With DataContractResolver by Kelly
Configuring Known Types Dynamically - Introducing the DataContractResolver by Youssef
Thanks for the replies regarding the Data Contract Resolver guys. I probably would have gone down this route normally but as I was using Windsor I was able to come up with a solution using this instead.
For anyone interested, I added a Windsor installer (IWindsorInstaller) to each of my "command" projects, which are run using Windsor's container.Install(FromAssembly.InDirectory.... These installs are responsible for registering any dependencies needed within that project, plus they also register all the command classes which my known types helper can resolve from the container.
Ok so I have built my WCF service and its functioning great! However, I am starting to implement it into our pre-existing piece of software now and I am instantly running into the question, do I only use the proxy generated code and get rid of the dll that I used initially? Or do I keep both, and make distinctions between the two very obvious?
What I mean by keeping distinctions is, having a ServerUser and a LocalUser property that represent the same user object. However, my LocalUser property would be filled via the dll that the app initally ran with, if the application service is unavailable.
My main reasoning for this thought pattern is that if I remove my dll, I have a single point of failure. If for some reason my ServiceHost is just not up and running, but the DB server is, I would want my users to still be able to do their job. The features that the new WCF implementation utilize are not dependant for employees to do their job. It is more of a convenience in what the WCF service provides. Also, building in this kind of logic to the Service would allow service modifications more readily available in a non IIS hosted environment.
Also, is there a way to build in logic on the service so that when I pull down the proxy code for the client that it just knows to access the DB manually if the ServiceHost is unavailable? If this was a possibility, I think about 90% of all my problems would disappear.
Thank you in advance!
From what you describe it sounds like keeping your existing DLL, i.e. direct access to the DB, would best suit your needs. Having a WCF service adds nothing if, when it fails, you'll just use the DLL anyway.
Ideally you would go with the WCF service completly and offer some kind of redundency to deal with any potenial service issues. Plus, using a service will mean you won't have to deal with any DLL upgrades/deployments.
But, from your question, it sounds like there would be some real issues to deal with should the service not be available, so just do with the DLL.
EDIT: Just read the last part of your question and I don't think that is possible. The proxy code for accessing services is generated when you add the reference to your project. The kind of "dynamic" information you're after would actually require a service.
EDIT: As a follow up to my comment below you could test this by creating a DLL and class, lets call it Class1. Then create a WCF service with a method that will return Class1. Create a client application and add a reference to the service. If you look at the proxy-generated code you should see (hopefully...I'm thinking of this as I type :)) that the method returns Class1, but when you compile it won't be able to find Class1. This is because Class1 does not have the DataContractAttribute which would auto-generate Class1 on the client. So, you have to distribute the shared DLL to the client. Now when the method returns and WCF tries to re-create Class1 it will use the local version in the shared DLL. Your other DLL, which will already be on the client, would use the same shared DLL.
looking at
WCF ChannelFactory vs generating proxy
appears that the best practice in creating a WCF client is to create a proxy (Not autogenerated).
I've been looking online for a while and i didn't find any complete example(Proxy class, web.config)
Could you provide an example or links to resources?
This article is about exactly what you're asking, I believe:
WCF the Manual Way... The Right Way
Having shared that, though, creating your proxies manually is probably not always the best possible use of your time. The article goes into some great reasons for doing so - you'll certainly have more control, your clients may have an easier time, etc. but overall, doing things manually like this will require more of your time, and explaining to users of your service exactly how to use the proxy you provide may be a pain.
There's a reason WCF allows metadata exchange and discovery and VS will auto create proxies for you.
Either way, it's a cool article and a technique well worth learning.
This is how I do it.
Get service contracts and data contracts
If I have access to the service code, I have all the contracts. If not, I can use svcutil or Add Service Reference to generate them.
Make config
I use Add Service Reference just to get the app.config file. I then delete everything else it generates. Edit the app.config as necessary.
Define factory
Say I have a service contract IFooService:
interface IFooServiceChannel : IFooService, IClientChannel { }
That is literally it. No members.
Create factory
fooServiceFactory = new ChannelFactory<IFooServiceChannel>(
"NetTcpBinding_IFooService");
The string "NetTcpBinding_IFooService" is the name attribute of the binding element in app.config.
Create channel
fooService = fooServiceFactory.CreateChannel();
Use it
fooService.DoSomething();
The trickiest part is getting app.config right. You need to learn about bindings and endpoints. It's a bit of a learning curve, but nothing drastic.
Here are the basic steps.
Create your service like normal.
Move the interface that your service implements into an assembly that can be shared with the client.
Create a ChannelFactory where T is your interface. You will have to give the uri of your service to the constructor.
Call factory.CreateChannel(). This will be type T.
Use the channel to make calls.
It is really that simple. No auto generated code, no service references. It gets a little more complicated with async calls and Silverlight, but not too much.
Consider the following Visual Studio project structure
ProjectA.csproj
AClass.cs
ProjectB.csproj
References
ProjectA
Web References
AWebService
AWebService.csproj
References
ProjectA
ReturnAClassViaWebService.asmx
The issue occurs when ProjectB adds the web reference to AWebService and automatically generates all the proxy code for accessing AWebService including a new implementation of AClass. Since all of our other code needs to use the AClass defined in ProjectA, we're forced to convert the AWebService.AClass returned from the service into something we can use.
We're currently considering two solutions, neither of which are ideal.
Manually editing the generated Reference.cs to remove new definitions of AClass
Serializing AWebService.AClass to a stream then deserializing to ProjectA.AClass
Does anyone have any better solutions? This seems like something common enough for other developers to have experienced it.
Ideally we would like to have the proxy code generated in ProjectB to reference ProjectA.AClass rather than generating a whole new implementation.
Our environment is VS 2008 using .NET 2.0.
I have had the same problem that you are describing and I have tried both of the options you specify without being entirely happy about either of them.
The reason we both have this issue is at least partly because the shared-library-between-consumer-and-provider-of-a-web-service-solution is in violation of accepted patterns and practices for web service design. On the consumer side, it should be sufficient to know the interface published in the WSDL.
Still, if you are prepared to accept a tight coupling between your web service provider and web service consumer and you know for certain that your current client will never be replaced by a different client (which might not be capable of referencing the shared library), then I understand why the proposed solution seems like a neat way to structure your app. IMPORTANT NOTE: Can we really honestly answer yes to both of these questions? Probably not.
To recap:
The issue appears when you have classes (e.g. a strongly typed dataset) defined in some sort of shared library (used on both client and server).
Some of your shared classes are used in the interface defined by your web service.
When the web reference is added there are proxy classes defined (for your shared classes) within the web reference namespace.
Due to the different namespaces the proxy class and its actual counterpart in the shared library are incompatible.
Here are four solutions that can be tried if you want to go ahead with the shared library setup:
Don't. Use the proxy class on the client side. This is how it is intendend to be done. It works fine unless you simultaneously want to leverage aspects of the shared library that are not exposed by the web service WSDL.
Implement or use a provided copy/duplication feature of the class (e.g. you could try to Merge() one strongly typed dataset into another). A Cast is obviosuly not possible, and the copy option is usually not a very good solution either since it tends to have undesirable side-effects. E.g. When you Merge a dataset into another, all the rows in the target dataset will be labeled as 'changed'. This could be resurrected with AcceptChanges(), but what if a couple of the received rows were actually changed.
Serialize everything - except for elementary data types - into strings (and back again on the consumer side). Loss of type safety is one important weakness of this approach.
Remove the explicit declaration of the shared class in Reference.cs and strip the namespace from the shared class wherever it is mentioned within Reference.cs. This is probably the best option. You get what you really wanted. The shared class is returned by the web service. The only irritating drawback with this solution is that your modifications to the reference.cs file is lost whenever you update your web reference. Trust me: It can be seriously annoying.
Here is a link to a similar discussion:
You can reuse existing referenced types between the client and service by clicking on the 'Advanced' button on the 'Add Service Reference' form. Make sure the 'Reuse types in referenced assemblies' checkbox is checked and when the service client is generated it should reuse all types from project A.
In past versions this has not always worked correctly and I've had to explicitly select the shared type assemblies by selecting the 'Reuse types in specified referenced assemblies' option and then checking the appropriate assemblies in the list box. However, I just tested this with VS 2008 SP1 and it appears to work as expected. Obviously, you need to make sure that the types that are being used by the service and client projects are both from project A.
Hope that this helps.
We encountered a similar problem with one of our projects. Because we had several dependencies, we ended up creating a circular reference because project 1 required objects from project 2, but project 2 could not be build before project 3, which relied on project 1 to be build.
To solve this problem, we extracted all the public standalone classes from both projects and placed them inside a single librarie. In the end we created something like this:
Framework.Objects
Framework.Interface
Framework.Implementation
WebService
The WebService would be linked to all projects in our case, whereas external parties would only be linking to the objects and interface classes to work with. The actuall implementation was coupled at runtime through reflection.
Hope this helps