If for example, you have customers, orders and products. Do you create a separate service for each of these business entities?
It kinda feels logical that you should create a service contract for each of these. However, since you have to explicitly specify the contract that your service will implement… this sort of forces you to create a separate service for each service contract, does it not?
Could you please tell me how you would handle this? Somehow it feels ungainly to have a service for ever business entity… :-(
In advance, many thanks and regards.
Services act on business entities, but are not business entities.
So customers, orders and products would be data contracts, not service contracts.
It's the actions you perform on those data contracts that form your service contract, and the actions you expose on an entity may or not be all the things that entity can do.
If, as I think you might be asking, each entity has common functionality (CRUD operations for example) then yes, you should have a separate service contact for a CRUD service on each entity (CustomerCRUDService, OrderCRUDService etc.) because web services don't support overloads on method signatures.
(From the comments)
There are a couple of ways.
1) Composite service contracts: For example I have a service that implements WSTransfer - this actually is comprised of two service contracts, IWSTransferResource and IWSTransferFactory. In turn I have an IWSTransfer service contract that just implements those separate contracts - public interface IWSTransfer : IWSTransferResource, IWSTransferFactory
2) But you don't even have to get that complicated, an implementation in WCF can implement multiple service contracts - MyServiceImpl : IMyContract1, IMyContract2. However each contract needs a separate endpoint, because endpoints are for service contracts, not implementation classes.
Related
I am building a WCF service.
The Data Contract objects will be the exact same as the Business Objects.
Should I create Data Contracts in my WCF service or reference my BO Layer and use those Business Objects in my WCF Operations?
I would split them in different projects:
Foo.DataContracts
Foo.BusinessModels
Foo.Services
Reference BusinessModels and DataContracts in Services. Then map the model classes to contract classes using AutoMapper and vice versa. You can then later change your models without breaking your WCF clients, since they rely on the contracts.
If your business objects can be serialized without muddling the concerns of serialization in with the business logic, then I'd say go for it.
A better alternative though is to bring your business logic layer behind the Services layer and expose simple DTOs from the service that your view can bind to.
I wrote an article on this approach with WCF RIA Services that translates pretty well to standard WCF Web Services
I think in the same line of #valpolushkin though I have not used AutoMapper till now.
See my answer in WCF Message & Data Contract, DTO, domain model, and shared assemblies for an example where the use of Business Entities as Data Contract can cause breaking changes.
I think, it is a very bad practice to use Business Objects as DataContracts. The Service need to be autonomous. The service may be used by clients that has / has not got Lax Versioning.
Refer Service Versioning.
It is easy to mistakenly believe that adding a new member will not break existing clients. If you are unsure that all clients can handle lax versioning, the recommendation is to use the strict versioning guidelines and treat data contracts as immutable.
Also, refer MSDN - Service Layer Guidelines
Design transformation objects that translate between business entities and data contracts.
Trying to really 'get' endpoint contracts:
I understand offering different endpoints to support different bindings, but when would one define n endpoints for a service, and use different contracts? Seems that in most cases (bar IMetadataExchange) the endpoint contract would be the same no matter the protocol, no?
If most of the time the contract would be the same across all endpoints, would it have been too simplistic (and why?) to define the service contract on the parent service instead of on each endpoint (seems cumbersome/repetitive), while alllowing an override on the endpoint for when needed (eg: IMetadataExchange).
Thanks for help with the small questions that keep me up at night ;-)
OK, well - the service that you define in the <service> tag is the actual implementation code - the actual C# or VB.NET lines that make up the service. Therefore, it's a concrete class (which might even implement multiple service contracts). This is server-side only.
The endpoint however is the communications channel between the server and the client, and between those two, you want to share only the contract - never any concrete implementation of that contract. The endpoint will only ever be used for a single service contract - if your concrete service implements multiple contracts, you need to expose multiple endpoints to the clients to provide all that functionality.
Does that make things a bit clearer?
I have Modification, Retrieval and Administration operations that are implemented by WCF services. I would like to separate them. The first thing that came to mind was to have three interfaces IRetrieval, IAdministration and IModification and create endpoints based on these interfaces. However, another developer said something about using different bindings or ports. I don't think that's possible - my understanding that WCF binding only defines how the data is treated over the wire and is not fit for logical separation. Am I in the ball park? Are there any other ways to separate the functionality besides the interfaces?
There are only two ways to separate functionalities: separate contracts implemented on the same service or separate contracts implemented on separate services. The difference between these two are more like logical and physical separation. For example default WSDL generation exposes metadata from all implemented contracts in a service. So if you implement all contracts in the single service and expose a metadata endpoint, each client will know an exact description of your administration methods and what security is used.
I have 2 contracts (cA & cB) implemented by a single WCF service with 2 endpoints (epA & epB).
This is not for security purposes, but purely for reasons of clarity/organization, I'd like to only "see" ContractA's operations when I discover the service via endpointA; and likewise, only see ContractB's operations via endpointB.
I don't need to "protect" these operations per se. The scenario is such that any given client only needs one "side" of the service, never both (but, the operations themselves share resources, so it makes sense to have a single service rather than 2 services).
It seems that any given service basically gets 1 WSDL, ergo all operations are exposed to all endpoints. Is that the way it works, or is there a way to "shape" an endpoint by occluding operations not defined by the endpoints contract?
By default, you're right - one service implementation class gets one WSDL which contains all service methods (from all service contracts) that this service class implements.
There are no ways present (as far as I know) to "shape" the WSDL in any (easy) way - WCF does offer ways to get into the process of creating the WSDL (statically or dynamically), but those aren't for the faint of heart. It would be much easier for you to just split the implementation of the service contracts into two separate classes and then you'd have two separate services, separate WSDL's and all.
Marc is absolutelly right. I'm just adding why this happens in WCF. In WCF all metadata related functionality are based around service metadata behavior and mex endpoint. Both these features are defined on service level. So you can't take higher granuality (unless you write a lot of custom code) and specify metadata per endpoint.
WCF service (class) is directly mapped to wsdl:service element which exposes each contract as separate wsdl:port (in WCF known as endpoint). This is the main point in answering your question. If you don't want your second contract in that wsdl:service you can't implement it in the same class.
You have mentioned that your service contracts share resources. In that case your WCF service probably also contains business logic. That is a reason for your problems. The good design for implementing WCF services is to create them only as wrappers around separate business logic classes.
I have a data contract say User. It is serializable and goes across the wire. I want an Operation Contract SaveUser(). I can keep SaveUser(User user) in my service contract as an operation contract. But can I keep it inside my data contract itself as its own behavior?
Save() should ideally save itself. So as per OO principles, every data contract should know how to save itself and the details should be abstracted from the outer world.
Is this possible in WCF?
I would say no, and rightly so.
Though I agree with you on the OO principles and encapsulation, WCF deals with SO (Service Oriented) principles.
Think of this in terms of a CD Player and CD's. The CD Player is the Service. The CD is the Data Contract. OO principles would call for the CD to have a Play method in order to be able to play itself. But, there is a lot more to playing a CD than knowing it's data. There is the electronics, the interface to the output jacks, etc. These are all provided by the CD Player...the Service.
So that is why your Service Contract has the Play method, and accepts the CD as a Data Contract telling it WHAT to play (and not HOW to play it).
EDIT after the question in your comment:
No certainly (hopefully) not. The worst case is that you will have 34 Service Contracts, each with on average 6 methods. And this is only the case if you are sure that every one of the methods on each class MUST happen as a service operation. There are 2 aspects you need to consider. Aspect 1: The design of your services. Instead of 34 Service Contracts, you should group the 34 classes into a grouping that makes sense, and create 1 Service Contract per group. Eg, you may end up with an InventoryManagement Service, and a SalesOrderProcessing service and a BackOfficeOperations Service. Each of these services contain the service operations (and Data Contracts) relevant to the range of classes grouped into their domain.
Aspect 2: What is happening on the client. I mentioned that you must consider whether each class's methods MUST be WCF Service Operations. There certainly is a case for having rich fully encapsulated business classes on the client. And where their operations don't need to execute as service operations, these operations execute their logic in the client domain. The question becomes how to get them to the client via a service, and here you have two alternatives: a) instantiate an instance on the client, and populate it's properties from the DataContract returned by a service operation. b) return the object directly from a service operation, as is done in a framework like CSLA (and I think DevForce follows a similar approach for returning business classes via a WCF Service).
HTH