I see a huge number of request and response types in a project to cater for all the endpoints exposed as WCF services. This seems like an awful lot of repetitive, simple code to maintain.
Can these types be auto-generated or avoided altogether using something like attributes?
They can be autogenerated a few ways. The two I'm most familiar with:
Web Service Software Factory - Modeling Edition. You maintain a UML-like model and let the factory generate much of your code. Code is generated as partial classes so you can manually add/override methods and more complex schema.
I also sometimes define all of the data in XML Schema, then use WSCF.blue to generate the contracts from the schema. Again, it creates partial classes so that you can tweak the generated contracts.
Related
I am currently in the process of developing a Web Service which should expose a relatively large number of ways to interact with it.
For example, Clients may be able to interact with the Web Service in order to manage users or projects in a Database.
To that effect, I created the following classes:
Two Data Contracts: IUsersServiceContract and IProjectsServiceContract
Two Service Contracts Interfaces: IUsersServiceContract and IProjectsServiceContract
My question is the following:
Does it make sense to create two different Web Services, each with their own endpoint(s), instead of creating one big class that implements both Service Contracts Interfaces ?
Keep in mind that in reality I would have many more Service Contracts Interfaces that deal with different sorts of data.
From what I understand, using a partial class (split in multiple files) will allow me to create one big Web Service with only one Endpoint.
This has the disadvantage of dealing with one big class split in multiple files, i.e: its harder to maintain and more prone to errors if developers "don't see the big picture".
The other solution would be to have one Web Service per Service Contract Interface implemented.
In essence, if I have X Service Contracts Interfaces, I end up with X Web Services with X Endpoints.
Which solution would you choose and why ?
Thanks for your input !
Personally I would not use partial classes for splitting a class; the sheer size motivating tgis split suggests that the class is too large and needs a refactoring. In my opinion partial classes main purpose is to add changes to auto generated code.
Since service and endpoint configuration can be shared using named behaviours in web.config splitting the service should not be that cumbersome. But the split should be motivated by grouping of functionality.
Without knowing the exact nature of you services it sounds like there could be a natural separation in two services; one for user related operations and one for project oriented operations.
If the implemantation classes grows above what you think are reasonable sizes I would consider letting separate classes - or preferably interfaces - handle each methods inner logic and let the service implementation it self be a shallow facade that delegates its own method parameters to the correct logoc instance
An important thing to consider here, when you're talking about n number of service contracts, is the cost associated with implementing each service contract. There's a good blog post on that here, "Service Contracts Factoring and Design", although if it wasn't Juval Lowy who posted this article then someone is clearly ripping him off (I am referring to Juval's book - "Programming WCF Services" page 93).
There are some pain points around transmitting entities between a client and a WCF service.
Defeating lazy loading by serializing all properties
Serialized data can be unecessarily bloated
Some coupling between UI and business layer
One way to address these issues is to transmit DTOs instead of entities but I am aware that this technique has its own set of caveats (the biggest one I am aware of is the typing required to maintain these function-specific DTOs).
I think it would be great if the service implementation could generate these DTOs dynamically and this appears to be possible. Unfortunately, it looks like the contract would be loosely defined on the client side (i.e. "object") and that smells like a possible risk.
Is it advisable to use dynamic DTOs in this fashion or is there another way to use DTOs without creating/maintaining classes for each one?
I think the holy grail would be where the implementation dynamically generates DTOs but the client sees well-defined contracts. I'm guessing this isn't possible with WCF.
I guess the issue is what are you going to generate them from? You have to have some description somewhere of what the data you want to transmit looks like. If all you have is the domain objects then you end up in a similar position of transmitting the data that you would of via the domain object.
One of the key things the DTO enables is decoupling so you can evolve your domain objects without breaking the consumers of your service accidently. If you dynamically generate the DTOs then you will cascade the changes - unless you view the dynamic creation as a one-off exercise to get you started with a DTO
DTO is data contract as any other and must be defined. When you choose to go with DTOs you are adding a layer of complexity which you have to maintain. There are tools which can help you with mapping between domain objects and DTOs (like AutoMapper) but your responsibility is to define what DTO should transfer - that is something which can hardly be done automatically. Even with automated tool you will still have to maintain some definition of DTOs which will be used to generate code.
I am in the processing of migrating from web services to WCF, and rather than trying to make old code work in WCF, I am just going to rebuild the services. As a part of this process, I have not figured out the best design to provide easy to consume services and also support future changes.
My service follows the pattern below; I actually have many more methods than this so duplication of code is an issue.
<ServiceContract()>
Public Interface IPublicApis
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataA(ByVal req As RequestA) As ResponseA
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataB(ByVal req As RequestB) As ResponseB
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataC(ByVal req As RequestC) As ResponseC
End Interface
Following this advice, I first created the schemas for the Request and Response objects. I then used SvcUtil to create the resulting classes so that I am assured the objects are consumable by other languages, and the clients will find the schemas easy to work with (no references to other schemas). However, because the Requests and Responses have similar data, I would like to use interfaces and inheritance so that I am not implementing multiple versions of the same code.
I have thought about writting my own version of the classes using interfaces and inheritance in a seperate class library, and implementing all of the logging, security, data retrieval logic there. Inside each operation I will just convert the RequestA to my InternalRequestA and call InternalRequestA's process function which will return an InternalResponseA. I will then convert that back to a ResponseA and send to the client.
Is this idea crazy?!? I am having problems finding another solution that takes advantage of inheritance internally, but still gives clean schemas to the client that support future updates.
The contracts created by using WCF data contracts generally produce relatively straight-forward schemas that are highly interoperable. I believe this was one of the guiding principles for the design of WCF. However, this interoperability relates to the messages themselves and not the objects that some other system might produce from them. How the messages are converted to/from objects at the other end entirely depends on the other system.
We have had no real issues using inheritance with data contract objects.
So, given that you clearly have control over the schemas (i.e. they are not being specified externally) and can make good use of WCF's inbuilt data contract capabilities, I struggle to see the benefit you will get the additional complexity and effort implied in your proposed approach.
In my view the logic associated with processing the messages should be kept entirely separate from the messages themselves.
Please note that my experience in Silverlight/.Net and WCF is about two weeks of googling and deciphering tutorials. I need to attempt and provide feedback to a client on if Silverlight will be a possible solution to their application needing a RIA front end.
The client has a rather large .Net based application with a UI layer built which greatly relies on the creation and manipulation of specific (personal) classes and objects from the backend (which would be the server side).
A summery of what I understand to be the general procedure: one can pass simple objects containing simple data types, or more complex .Net type objects. Basically anything which can be understood by both client and server side, after serializing.
But what is the limitation to the complexity of an object I can pass? Or phrased otherwise, would silverlight and WCF be able to support the passing of a personalized object which may contain references to other classes/objects and variables etc?
Additional Info (in case it can help):
I am not allowed direct access to their backend code but with the information I have been given I can safely say their classes heavily use inheritance and overloading of functions/methods in the classes.
As far as I know there is nothing specific to Silverlight. There are some things to keep in mind though.
WCF serialization doesn´t like circular references.
All types need to specified in the contract. So watch out with inheritance etc.
In general using DTO's (Data Transfer Objects) and not exposing your business objects is the way to go.
The metaphor is one of message passing as opposed to passing objects. DTO's as Maurice said.
You can get pretty complex, but each object needs to have its contract defined.
I've been coming up with a lot of dead ends on this question. Supposedly, .NET 3.5 SP1 has Support for ADO.NET Entity Framework entities in WCF contracts. But when I look for solid info on it I'm not getting a lot of answers. I found this one snippet on an MSDN thread. Does anyone have any experience with this? What happened to the [DataContract]? Is this all there is to it? Why is there so little material on this?
This the answer from Tim Mallalieu in Microsoft.
Entity Types that are generated in the Entity Framework are, by default Data Contracts.
If I were to create a simple model in the Entity Designer like the following:
The cart Entity Type is by default a DataContract with all properties annotated as data members. We can then use this in a WCF service as follows:
[ServiceContract]
public interface IService1
{
[OperationContract]
Cart[] AllCarts();
}
public class Service1 : IService1
{
public Cart[] AllCarts()
{
using (MSPetShop4Entities context = new MSPetShop4Entities())
{
var carts = from c in context.Carts select c;
return carts.ToArray();
}
}
}
As the Entities are DataContracts you can now roll your services as you see fit and send these across the wire.
I recommend that you not return Entities directly. Unfortunately, Microsoft chose to include implementation-specific data as part of the DataContract for entities. This will not interoperate with other platforms, and is the sort of thing that might fail to interoperate even between .NET versions.
Instead, I recommend you follow the Data Transfer Object pattern and just return POCO classes that are copies of the data in the entities, with no behavior. You can return List of such classes to represent a table, etc.
The "sharing interfaces and not type" tenet presupposes that you don't own both ends of the wire and/or you're writing a public-facing web service. WCF can be used (and is used) in contexts where this is decidedly not the case. Many enterprise n-tier architectures have a WCF-fronted application tier to facilitate load-balancing among other things. In these cases it is perfectly valid to share type and, in fact, is desired.
You could go the easy way and use ADO.NET Data Services.
Some more detail in response to comments:
There are several problems with the classes generated by EF. I'm looking now at an AdventureWorks example with SalesOrderHeader and SalesOrderDetail. The SalesOrderDetail entity has both "SalesOrderHeader" and "SalesOrderHeaderReference" properties, both marked as DataMembers. This looks like a bug, since the "SalesOrderHeader" property is also marked [XmlIgnore] and [SoapIgnore].
Also, consider whether you want to serialize the link back to the parent SalesOrderHeader in the first place. Besides, what exactly should be serialized? SOAP doesn't support references in an interoperable manner.
Finally, the base classes of the entities are also data contracts. Yet they have nothing to do with the data you are returning - they are purely an implementation artifact.
In short, Microsoft screwed up on this one. They didn't think it through.
About ways to generate the DTO classes, I suggest looking into various code generation tools, like CodeSmith. You can write code to do this yourself; I did so in my previous position. The nice thing about generating the DTO is that you also get to generate the methods to translate to and from the DTO.
As to overhead, the overhead of moving some data around in memory is nothing compared to the amount of time it's going to take to send the data over a network!