Can a WCF data contract contain a WCF operation contract inside it? Why? - wcf

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

Related

Interaction of services in the service layer

What is the best way to organize interaction between services in the service layer?
For example, I have document service and product service. In my case products can have their own documents and to manage documents of product I call appropriate methods from the document service in the product service. So, I need to create instance of document service in product service. And I need to call some methods from product service in the document service too. So, each of these services refers to other and I get stackoverflowexception respectively.
Which design solutions should I use to eliminate these problem?
Application Services are supposed to provide external clients an API for executing cohesive business operations. An application service method generally matches a use case of your application.
While an application service operation may require calling another service (eg, the Create Product use case includes the Create Document use case, which can also be called separately), this is not the norm and you should look to make your application services as cohesive as possible. In particular, just because at some point in your business case you start to manipulate another kind of entity doesn't mean you should delegate that part to another application service - in other words, one application service per entity is not necessarily right.
In any case, from your domain it should appear clearly in which direction the dependency between 2 applications services points. In your example, Product Service seems to depend on Document Service - it's difficult to imagine why it would be the other way around.
If you really need a round-trip between service A and service B (which I wouldn't do unless I have no other option), you could try and have the instance of A inject itself into B instead of relying on a DI container to resolve the dependency with a new instance, solving the stack overflow problem - if that's why you get a stack overflow in the first place.
Obviously, circular dependencies are wrong.
You can use shared identifiers to decouple Products and Documents.
Moreover you can orchestrate the service interaction from outside them, in the application: in the ProductService you can have a LoadProducts(ProductIdentifiers[] identifiers) returning an immutable collection of products and in the DocumentService you can have a LoadDocuments(DocumentIdentifiers[] identifiers) returning an immutable collection of documents.

WCF Service and Business Logic

I am unsure where to place my business logic. I have a WCF service which exposes its methods to my client.
Should my business logic go in the service method
public User GetUser(int id)
{
//Retrieve the user from a repository and perform business logic
return user;
}
or should it be in a separate class where each WCF service method will in turn call the business layer methods.
public User GetUser(int id)
{
return _userLogic.GetUser(id);
}
My personal preference is to have WCF as a very thin layer on top of a separate business layer. The WCF layer does nothing more than make calls to the business layer, similar to what you have shown in option 2. This gives you some flexibility in the event that you want to have your business layer consumed by something other than WCF clients (for example, a WPF application calling your business layer directly rather than via WCF).
WCF services are already, by default, designed for reuse. I see no reason not to have some logic in your services, though keep in mind things like the Single Responsibility Principle so you don't end up with a service that does a dozen things.
Even then, if you end up parceling out your functionality into smaller classes, it's not a bad idea at all to host those classes as WCF services. You can then use them in-proc (via pipes) when needed or across machine boundaries (tcp) or even as web services. Create facades as needed to provide access to the functionality of your other, smaller services.
There's no real need to avoid putting any logic in WCF service classes.
I think that the decision depends on your business needs. WCF is a mechanism to transport data (objects) between server and client. If you like your businsess logic runs on server, you should let WCF exposes the object after running your business logic.
It should go in a separate set of classes. Your WCF layer should only contain logic that directly pertains to how the product of the service is delivered.
In your case, I see that you have a WCF method that returns a User (I assume this is a custom class) why have a separate method to return the UserID instead of populating that property as part of returning the User object?
For reuse/testability/maintenance/readability you should always put you BL in a separate layer.

Need some advice for a web service API?

My company has a product that will I feel can benefit from a web service API. We are using MSMQ to route messages back and forth through the backend system. Currently we are building an ASP.Net application that communicates with a web service (WCF) that, in turn, talks to MSMQ for us. Later on down the road, we may have other client applications (not necessarily written in .Net). The message going into MSMQ is an object that has a property made up of an array of strings. There is also a property that contains the command (a string) that will be routed through the system. Personally, I am not a huge fan of this, but I was told it is for scalability and every system can use strings.
My thought, regarding the web services was to model some objects based on our data that can be passed into and out of the web services so they are easily consumed by the client. Initially, I was passing the message object, mentioned above, with the array of strings in it. I was finding that I was creating objects on the client to represent that data, making the client responsible for creating those objects. I feel the web service layer should really be handling this. That is how I have always worked with services. I did this so it was easier for me to move data around the client.
It was recommended to our group we should maintain the “single entry point” into the system by offering an object that contains commands and have one web service to take care of everything. So, the web service would have one method in it, Let’s call it MakeRequest and it would return an object (either serialized XML or JSON). The suggestion was to have a base object that may contain some sort of list of commands that other objects can inherit from. Any other object may have its own command structure, but still inherit base commands. What is passed back from the service is not clear right now, but it could be that “message object” with an object attached to it representing the data. I don’t know.
My recommendation was to model our objects after our actual data and create services for the types of data we are working with. We would create a base service interface that would house any common methods used for all services. So for example, GetById, GetByName, GetAll, Save, etc. Anything specific to a given service would be implemented for that specific implementation. So a User service may have a method GetUserByUsernameAndPassword, but since it implements the base interface it would also contain the “base” methods. We would have several methods in a service that would return the type of object expected, based on the service being called. We could house everything in one service, but I still would like to get something back that is more usable. I feel this approach leaves the client out of making decisions about what commands to be passed. When I connect to a User service and call the method GetById(int id) I would expect to get back a User object.
I had the luxury of working with MS when I started developing WCF services. So, I have a good foundation and understanding of the technology, but I am not the one designing it this time.
So, I am not opposed to the “single entry point” idea, but any thoughts about why either approach is more scalable than the other would be appreciated. I have never worked with such a systematic approach to a service layer before. Maybe I need to get over that?
I think there are merits to both approaches.
Typically, if you are writing an API that is going to be consumed by a completely separate group of developers (perhaps in another company), then you want the API to be as self-explanative and discoverable as possible. Having specific web service methods that return specific objects is much easier to work with from the consumer's perspective.
However, many companies use web services as one of many layers to their applications. In this case, it may reduce maintenance to have a generic API. I've seen some clever mechanisms that require no changes whatsoever to the service in order to add another column to a table that is returned from the database.
My personal preference is for the specific API. I think that the specific methods are much easier to work with - and are largely self-documenting. The specific operation needs to be executed at some point, so why not expose it for what it is? You'd get laughed at if you wrote:
public void MyApiMethod(string operationToPerform, params object[] args)
{
switch(operationToPerform)
{
case "InsertCustomer":
InsertCustomer(args);
break;
case "UpdateCustomer":
UpdateCustomer(args);
break;
...
case "Juggle5BallsAtOnce":
Juggle5BallsAtOnce(args);
break;
}
}
So why do that with a Web Service? It'd be much better to have:
public void InsertCustomer(Customer customer)
{
...
}
public void UpdateCustomer(Customer customer)
{
...
}
...
public void Juggle5BallsAtOnce(bool useApplesAndEatThemConcurrently)
{
...
}

Shape a WCF service by endpoint

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.

WCF Business logic handling

I have a WCF service that supports about 10 contracts, we have been supporting a client with all the business rules specific to this client now we have another client who will be using the exact same contracts (so we cannot change that) they will be calling the service exactly the same way the previous client called now the only way we can differentiate between the two clients is by one of the input parameters. Based on this input parameter we have to use a slightly different business logic – the logic for both the Client will be same 50% of the time the remainder will have different logic (across Business / DAL layers) . I don’t want to use if else statement in each of contract implementation to differentiate and reroute the logic also what if another client comes in. Is there a clean way of handling a situation like this. I am using framework 3.5. Like I said I cannot change any of the contracts (service / data contract ) or the current service calling infrastructure for the new client. Thanks
Can you possibly host the services twice and have the clients connect to the right one? Apart from that, you have to use some kind of if-else, I guess.
I can't say whether this is applicable to you, but we have solved a similar problem along this path:
We add a Header information to the message that states in which context some logic is called.
This information ends up in a RequestContext class.
We delegate responsibility of instantiating the implementation of the contract to a DI Container (in our case StructureMap)
We have defined a strategy how certain components are to be provided by the container:
There is a default for a component of some kind.
Attributes can be placed on specializations that denote for which type of request context this specialization should be used.
This is registered into the container through available mechanisms
We make a call to the Container by stating ObjectFactory.With(requestcontext).getInstance<CONTRACT>()
Dependencies of the service implementations are now resolved in a way that the described process is applied. That is, specializations are provided based ultimately on a request information placed in the header.
This is an example how this may be solvable.