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
Related
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.
In the last 2 years I've been developing a distributed application in c# 3.5 using WCF at communication tier on TCP/IP protocol; so far I've been using the integrated Add Service Reference... to generate service proxies on the client side, but I also know that using channel factories to create a communication channel (thus accessing service contract methods) is a viable approach.
The questions are pretty straightforward (please argument the answers):
Which are the pros & cons of either approach?
Should the "automatic" generation method be preferred in most contexts, and if so, why?
Under wich circustances (if any) is the "custom" approach justified/needed?
(please tell me if more contextualization is needed to answer)
For me the one reason to use custom proxies is to be able to use the same interface[type] and domain types on both the client and the server. The automatic generation creates quite a few classes that will inevitably increase the size of your assembly, so if you're building a silverlight app where download time is critical or if you have a hefty memory constraint, channel factory might be the way to go.
I also like the DRY-ness of channel factory, since i typically have my domain objects anyway, why generate them again? Especially if i have a bunch of buisness logic in them. Ofcourse, that is really only applicable to wcf-to-wcf communication, if you're talking to any other service, you'd want to have the domain objects generated
(Im also assuming here that the domain types and interfaces are in their own assembly, separate from the actual back-end persistance code)
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
I have a webservice with a function that returns a type (foo). If I consume this webservice in .NET through the 2.0 generated proxies, it creates a class called foo in the generated proxy. If I have the DLL that contains that class (foo) that is the DLL being used by the webservice, is there any way to have it use that class instead of creating a custom proxy class? I'm looking for something similar to what remoting does... but not remoting.
I've seen 3 ways of doing this:
Let Visual Studio generate the proxy and then change the classes in the proxy to the full class names of the dll, by hand. Works, but you would have to do this again everytime you update your proxy. Plus it's really dirty, isn't it?
Use a generic class/method that
creates deep copies of your proxy
objects into the "real" objects by
reflection. Works, but of course
with a little performance offtrade
Use WCF, where you can reference the
dll with the data contracts (your
data classes) and use them instead
of creating any proxy by code
generation.
I think the key issue here is in generating the proxies. I've generally used two different approaches to web services:
1) Traditional services, where you expose methods and a client generates the proxy in Visual Studio to consume the methods.
2) Request/Response services, where the exposed "service" is more of a pass-through and the "actions" being performed are encapsulated in the objects being sent to and received from the service. These actions would be in that shared library that both the server and the client have.
In the former I often run into this same problem and I don't really think there's a solution, at least not one that Visual Studio is going to like at all. You could perhaps manually modify the generated proxies to use the other classes, but then you'll have to repeat that step any time you re-generate. Conversely, you can generate outside of Visual Studio in something like CodeSmith (the older version is free, but depends on .NET 1.1), which will require some work to create a template for the proxies and to step outside the IDE to re-generate any time you need to update them.
I can recommend a good tool for the latter, however, and that would be the Agatha project. It takes the approach of separating the "service" from the "actions" that are being performed, and makes the approach of the shared library very easy. Such a re-architecture may very well be out of the question for the project you're working on depending on your schedule, but it's definitely something to explore for future projects.
You could write your own proxy class, or you could implement a constructor on your Foo class that takes an instance of the generated Foo class and copies over the data as appropriate.
I just referenced my application domain layer dll to the new WCF service that I am creating.
On my initial tests I am able to use and return the objects from my domain layer on the WCF service.
Question that come in my mind is none of my domain claseses have [DataContract] attribute so does this create a limitation or problem for me that I should be aware of? Or any other concerns that I should know when using other class library in a WCF project?
You can either use DataContract or Serializable. If you use serializable you need to reference the dll with the types from both the server and the client. This is Ok when you have control of both, but can be a problem if other people want to access your service.
Take a look at this video for a better way of doing it than standard Visual Studio:
http://www.dnrtv.com/default.aspx?showNum=122
First law of distributed object design : don't distribute your objects.
But if you really want because you create a data oriented application, .NET Ria Services is what you want.