Moving WCF contracts to a separate dll - c#

I want to move WCF contracts interfaces to third DLL and start consuming them from clients when I am generating proxy by hand.
Do those interfaces in the DLL have to have the [ServiceContract] attribute when I consume them from the client to generate a proxy ?
Any idea what is the best naming for Dll that will have only contracts and the DTOs to share between client and the server.

It is very common practice to put WCF data and service contract to separate assembly. In my previous project we used naming like Company.OurProject.Contracts.dll.
I think that to generate proxy with reusing existing classes you should put your interfaces for service contracts (those marked with [ServiceContractAttribute]) and corresponding data contracts to that assembly. I would avoid putting there actual implementation of the services.
Here is another great answer on SO with more insight into what can be reused when "Reuse types in referenced assemblies" is selected: WCF Service Reference generates its own contract interface, won't reuse mine

This is common and perhaps recommended approach.
Yes you should put the service contract on the service interface which will live in the contract dll.
Keep in mind that the namespace does not have to match the name of the dll. Assuming that your current assembly is something like CompanyName.Technology.Service.dll with a namespace like CompanyName.Technology.Service you should extract out the contract to another assembly BUT keep the namespace the same (providing it still makes sense to) and have an assembly name of CompanyName.Technology.Service.Contracts. What you do not want to have is a namespace with the name "contracts" in it.

I use *.ServiceContracts.dll because I end up having multiple contract assemblies in my systems. DataContracts.dll for example is used for accessing data stores.

Related

WCF Multiple Services with DataContracts as Parameters C#

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.

WCF ServiceKnownType design issue

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.

WCF N-Tier Architecture

I'm working on a fairly straight forward multi-tier application (WPF, WCF, EF 4, and SQL). As far as architecture is concerned, we were planning to include a single "Common" project which will include both entities as well as service contracts.
Are there any advantages/disadvantages to having entities and service contracts in separate assemblies? Or is it usually good to keep them together?
I'm interested in hearing the opinion of others.
Thanks!
Having Contracts in a separate assembly gives you the advantage of the ability injecting to a different entities in a different assembly by providing the Contracts assembly to a developer , and he would implement it and give you a dll that you can put inside the project folder and inject to it using IoC framework like StructureMap without rebuilding,
having the contracts in the same assembly that contains the entities tie the contracts to the implementations...
If you are using a RESTful architecture with other .NET platform consumers - it's helpful to have the Service Contracts in a separate assembly (Shared) so that you can easily share your operation and data contracts with RESTful consumers without exposing any unnecessary data access components to your clients.
I would recommend that you keep the data access and service contracts isolated for this reason.
That is exactly how I structured the design for an e-commerce n-tier app I designed.
There are two common libraries - one for DTO's and another for interfaces.
Then the client and server included those librarues, and the service proxies were generated using common types.
The main advantage here is ease of compilation - you don't have to recreate the proxies when you change the insterface, the client and server are updated automatically.
I also had a utilities app that contained all the helper type stuff I needed.
EDIT: Sorry, just re-read your question. In my case, I had multiple interface libraries - one for the workflow library (with composed interfaces), and another for services (the thing being composed into workflow operations)
So in my case it made sense to keep them seperate.
If you only have one set of interfaces, and those interfaces all make use of your DTO's, there is no reason to seperate them into two libraries - one would be sufficient. Consider though if you may need to share your DTO's between more interface libraries in future, in that case rather keep the DTO's seperate from the interfaces from the start.

Adding WCF Service References to multiple projects

A couple of very basic questions. I am new to WCF and I am building an application which has a Service Project, A Web Application project and a few Class library projects which I use for Business logic, etc.
I am hosting the WCF locally on my IIS and trying to add service references to the projects.
Question 1. When adding references, should I add a service reference to each project separately or is there a way I can share the same Service reference across the projects?
The reason I ask is because if I add separate references, each reference gets it own namespace, and when I have to pass the same object between the projects, I get an InvalidCastException because each ServiceClient has a different namespace.
Example -
Site.Business.XDataService.XDataServiceClient().GetItem()
is not the same as
Site.Web.XDataService.XDataServiceClient().GetItem()
Question 2. I specified the address of the local service in the class that implements the Service interface as below -
[ServiceBehavior(Namespace = "http://localhost:801/XDataService.svc", IncludeExceptionDetailInFaults = true)]
This doesn't seem right. If I move my code to a different/live environment, I would obviously have to change this part again and recompile. Where can I specify this (Web.Config?) so that I can change this address without having to rebuild my app?
Appreciate any kind of insight.
Thanks!
In answer to the first question, you can put the service reference in its own project and reference that project in all the other projects that need to access that service.
Basically all the service reference is is a lump of .NET code - namespace, class, etc.
Better yet (!) for a WCF service you also get an interface thrown in for free (more or less the same interface that you defined for your service) so you can do nice things in terms of dependency injection making testing etc easier.
First question - the service is just like any other code. For example, database access code. Should you put that in every project that needs to access your database? No - you should put it in a project which those other projects can reference.
As for your second question, you're specifying a namespace but I expect you think you're specifying a service endpoint address. The namespace is just like a C# code namespace - it essentially provides further identification and clarity in the event that you have multiple objects with the same name. Normally you'd use a namespace like http://mywebsite.com/MyService/VersionNumberIfRequired or similar.
The address itself is specified in configuration. The address will change depending on environment / deployment location - the namespace shouldn't.

.NET: DDD and ASMX, avoid multiple namespaces on proxy classes

I am new to DDD and at the moment I try to refactor a project towards a domain driven architecture. The project has a client and a server side (ASMX webservice). Now I created a class libary called "Domain" which is referenced by the client application as well as by the server.
Now I want my SOAP communication to be based on my domain model. But as you know the ASMX webservice creates some kind of proxy class library within the client as soon as a web reference is established.
This results in having each domain entity and value object twice under different namespaces.
Is it possible to use the domain model for communication directly and avoid the generation of the ASMX proxy classes?
How are DTOs used within DDD? As you know, some domain parts might not be serializable (e.g. NHibernate / IList usage) so in the past I often created simpler DTO-versions of my entity classes. Is it a common practice to define DTO entities within the domain?
If you were to use WCF, you could have the service interface and DTO classes in a shared assembly that both the client and the server referenced. Converting your project to use WCF may not be too hard, but there is a lot of learning to do before you get started.
A shared interface assembly is only a good ideal if you wish the client and server to be tightly joined, hence it does not work well unless both side are owned by the same team.
Often trying to use the same classes on the server and client lean to deign problem, however sharing classes when it does fit the design saves a lot of work.
(Sorry I don’t think you can used a shared assembly with asmx, it is more a concept from the remoting side of .net history)
It is not possible to use original domain model (obtained by a reference -not a WEB reference- to the domain model) for communication with the ASMX: you must use the model exposed by asmx that is similar but not the same (i.e. List are transformed in Array).
It's possible -and easy- create many classes from many web-services having the same namespace.
Create a .bat file like this
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\wsdl.exe" /sharetypes /o:C:\code\MyProxy.cs /namespace:MyProxies http://website/FirstService.asmx http://website/SecondService.asmx
Pause
Where
-"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\wsdl.exe" is wsdl.exe with relative path (it must be on your PC)
-/sharetypes means that you want only 1 namespace in the output
- /o:C:\code\MyProxy.cs is the .cs file name that will contain all the classes created
- /namespace:MyProxies is the namespace for all the classes created
- http://website/FirstService.asmx http://website/SecondService.asmx is the list of webservices that you need to call
- Pause means that you want window's shel to remain open to read the feedback of the operations.
NOTE
1) All instructions must be in one line (don't press enter); Pause in the second line.
2) If /o:C:\code\MyProxy.cs will be part of your solution (i think so) and you use source control, the file must be checked out to be overwritten by wsdl.exe

Categories

Resources