Need some advice for a web service API? - wcf

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)
{
...
}

Related

What if the best way to return Option types by WCF service

I have a WCF method which search the record in database and return Some(object) if the record exists and None if it doesn't.
As I see I can't call the method which returns Type option through WCF (I get exception).
What is the best way to design WCF services in F# in this way?
For example, I can return empty Type
Person
{
Name = ""
Age = 0
// ....
}
if the record doesn't exist in DB, but I am looking for the best ideas...
A WCF service, just like a RESTful service, exposes an API that can be accessed by remote clients. These clients need not even be written in .NET, but could be Java clients, or written in a completely different language, for all we know.
The entire point of SOAP and REST is to enable those interoperability scenarios, but that also means that services may share schema and contract, but not class (or any other type, for that matter).
A few years ago, I wrote an article called At the Boundaries, Applications are Not Object-Oriented, but you can take that article, and replace Object-Oriented with Functional: At the Boundaries, Applications are Not Functional (Programming).
Even if you could somehow serialize option types in WCF, you'd be advised not to do so, because clients may not understand what it means, or be able to handle that serialized format in any meaningful way.
In the end, an option can be viewed as a constrained collection with the constraint that it can hold either 0 or 1 element. You can't model that constraint when you return data over an interoperable service, but you can still return a collection/array.
That's what I sometimes do: return an array with either no element, or a single element. Most clients understand that.
When building RESTful services, you have the better option of returning 404 (Not found) when a resource doesn't exist, but I'm not sure there's a good way to do this with SOAP.
With SOAP, though, you can define data structures using XSD, so you might be able to use xsd.choice to model a data structure that can be either none or some.

Communication between two WCF service libraries on the same Windows Service host

The project I'm currently working on includes a server that receives C# scripts (partial code) from clients, wraps it to create a complete class, compiles it then load it into a separate AppDomain for execution.
A task (currently running script) can send feedback to the user at any point of it's execution, as defined in the script by the user. And possibly the task might wait for a response from the user (currently assuming it's only right after having sent feedback). And the user might, at any moment, decide to kill a task.
The server is implemented as a Windows Service hosting a WCF Service Library.
As I don't want to overcomplicate the client to make it communicate directly with the dynamically created AppDomains, the (partial) solution that I considered after some research was hosting a second WCF service with named pipe binding to make the dynamic AppDomains use it as a relay between them and the client facing WCF service.
My issue is that now I can't think of a clean way to have the two WCF services interact.
My ideas are:
Having them maintain direct references to each other:
Seeing as Normally both of the services are singletons it shouldn't be hard to do.
But that would be a pain to maintain in the case one of them fails and needs to be restarted. (I'm still new to WCF so I have no idea how common that is, but it's still an issue to consider. I think.)
Introducing some sort of a "message queue" (or two, one for each direction) with properties that can be set and subscribed to. Thus when one service sets a property an event will be triggered in the second. But that feels somewhat hacky to me, even though I can't really think of any clear issues.
I could really use some expert input on what I'm trying to accomplish, be it opinions on my thoughts or new ideas. Even if that involves rethinking the architecture. This project is still in an early enough stage to afford some rework, as long as there is enough reason to do that of course.
Since I've put lots of efforts (read: 2 minutes on paint) to prepare a quick (read: useless) schema of the system, I'll link it here since I don't have the reputation to post images:
Link to schema
Edit:
As I now have the reputation thanks to an upvote:
Still after rereading my question, I feel that perhaps I have been looking at this issue from a too narrow perspective by thinking of the services as something more special than ordinary classes. The more I think about it the more I feel that the observer pattern is probably the best approach to take.
Just for the record, and to avoid leaving my (silly) question unanswered, I've realised that I was looking at this too narrowly by trying to find a solution specific to WCF services.
And finally I ended up using a variation of the observer pattern (based on the IObservable<T>Interface).
I came across the same issue. The way I handled a duplex communication between the two servers is as following:
For each process (AppDomain Seperated Task) create a pair of WCF services. Both services have their Instancing set to PerSession (no need for singleton which may cause problems in the long run like disconnect). This means the Client will be communicating for each process (AppDomain Separated Task) with two distinct Service instances or a service pair (i.e. Service1 and Service2).
We want a duplex communication in between these two services, which means that both can communicate with the other and pass data (in the form of a DataContract class object).
For this:
1- Declare two services (i.e. in a separate class library) and host them (self hosting or else).
2- Create your DataContract class and add any property, collection, enum etc. as you like. Both services must have a get-set property for this class.
3- In the same class library (where the Service1 and 2 classes reside), create another class. This class will act as a depository for the Service pair instances. It has a static List in order to register the service pair instances (you can identify each service with a GUID).
4- We setup the client proxy using svcUtil.exe (or by code). When the client makes a service request, a service (i.e. service1) will be created by the WCF. At service1, create or launch the process (App Domain Separated Task) as client2 and at its constructor create the Service2 proxy by code.
5- Initialize the Service2 instance (i.e. by a call to the service2) and register the service pair instances at static list of the depository (so that it can be retrieved later for duplex communication). Now we have both service instances and both of them are registered as a pair into a static list.
6- Start communication between both services by making a call from Client1 proxy.
7- At Service1 call method, retrieve the service pair from the static list. Deep copy (DeepClone) the Datacontract class object from Service1 to the Service2 using the get-set property mentioned at (2). (Note that you can use one of the many Deep Clone libraries from Nuget like DeepCloner).
8- Make a call back from Service2. Client2 now has the identical DataContract class property values as Client1
9- Repeat steps 6-8 for Client2 proxy for Service2-Service1 communication.

Is shared assembly the only way to create objects from WCF REST service

I am writing an application that is consuming an in-house WCF-based REST service and I'll admit to being a REST newbie. Since I can't use the "Add Service Reference", I don't have ready-made proxy objects representing the return types from the service methods. So far the only way I've been able to work with the service is by sharing the assembly containing the data types exposed by the service.
My problem with this arrangment is that I see only two possibilities:
Implement DTOs (DataContracts) and expose those types from my service. I would still have to share an assembly but this approach would limit the types contained in the assembly to the service contract and DTOs. I don't like to use DTOs just for the sake of using them, though as they add another layer of abstraction and processing time to convert from domain object to DTO and vice versa. Plus, if I want to have business rules, validation, etc. on the client, I'd have to share the domain objects anyways, so is the added complexity necessary.
Support serialization of my domain objects, expose those types and share that assembly. This would allow me to share business and validation logic with the client but it also exposes parts of my domain objects to the client that are meant only for the service app.
Perhaps an example would help the discussion...
My client application will display a list of documents that is obtained from the REST service (a GET operation). The service returns an array of DocumentInfo objects (lightweight, read-only representation of a Document).
When the user selects one of the items, the client retrieves the full Document object from the REST service (GET by id) and displays a data entry form so the user can modify the object. We would want validation rules for a rich user experience.
When the user commits the changes, the Document object is submitted to the REST service (a PUT operation) where it is persisted to the back-end data store.
If the state of the Document allows, the user may "Publish" the Document. In this case, the client POSTs a request to the REST service with the Document.ID value and the service performs the operation by retrieving the server-side Document domain object and calling the Publish method. The Publish method should not be available to the client application.
As I see it, my Document and DocumentInfo objects would have to be in a shared assembly. Doing this makes Document.Publish available to the client. One idea to hide it would be to make the method internal and add an InternalsVisibleTo attribute that allows my service app to call the method and not the client but this seems "smelly."
Am I on the right track or completely missing something?
The classes you use on the server should not be the same classes you use on the client (apart from during the data transfer itself). The best approach is to create a package (assembly/project) containing DTOs, and share these between the server and the client. You did mention that you don't want to create DTO's for the sake of it, but it is best practice. The performance impact of adding extra layers is negligible, and layering actually helps make your application easier to develop and maintain (avoiding situations like yours where the client has access to server code).
I suggest starting with the following packages:
Service: Resides on server only, exposes the service and contains server application logic.
DTO: Resides on both server and client. Contains simple classes which contain data which need to be passed between server and client. Classes have no code apart from properties. These are short lived objects which survive long enough only to transfer data.
Repository: Resides on client only. Calls the server, and turns Model objects into DTO's (and vice versa).
Model: Resides on client only. Contains classes which represent business objects and relationships. Model objects stay in memory throughout the life of the application.
Your client application code should call into Repository to get Model objects (you might also consider looking into MVVM if your not sure how to go about this).
If your service code is sufficiently complex that it needs access to Model classes, you should create a separate Model package (obviously give it a different name) - the only classes which should exist both on server and client are DTO classes.
I thought that I'd post the approach I took while giving credit to both Greg and Jake for helping guide me down the path.
While Jake is correct that deserializing the data on the client can be done with any type as long as it implements the same data contract, enforcing this without WSDL can be a bit tricky. I'm in an environment where other developers will be working with my solution both to support and maintain the existing as well as creating new clients that consume my service. They are used to "Add Service Reference" and going.
Greg's points about using different objects on the client and the server were the most helpful. I was trying to minimize duplicate by sharing my domain layer between the client and the server and that was the root of my confusion. As soon as I separated these into two distinct applications and looked at them in isolation, each with their own use cases, the picture became clearer.
As a result, I am now sharing a Contracts assembly which contains my service contracts so that a client can easily create a channel to the server (using WCF on the client-side) and data contracts representing the DTOs passed between client and service.
On the client, I have ViewModel objects which wrap the Model objects (data contracts) for the UI and use a service agent class to communicate with the service using the service contracts from the shared assembly. So when the user clicks the "Publish" button in the UI, the controller (or command in WPF/SL) calls the Publish method on the service agent passing in the ID of the document to publish. The service agent relays the request to the REST API (Publish operation).
On the server, the REST API is implemented using the same service contracts. In this case, the service works with my domain services, repositories and domain objects to carry out the tasks. So when the Publish service operation is invoked, the service retrieves the Document domain object from the DocumentRepository, calls the Publish method on the object which updates the internal state of the object and then the service passes the updated object to the Update method of the repository to persist the changes.
I am pleased with the outcome as I believe this gives me a more robust and extensible architecture to work with. I can change the ViewModels as needed to support the UI with no concern over poluting the service(s) and, likewise, change the internal implementation of the service operations (domain layer) without affecting the client application(s). All that binds the two are the contracts they share. Pretty clean.
You can serialize your domain objects and then de-serialize them into different types on the client. Both types need to implement the same data contract. All serializable types have at least a default data contract that includes all public read/write properties and fields.

How to handle multiple storage backends transparently

I'm working with an application right now that uses a third-party API for handling some batch email-related tasks, and in order for that to work, we need to store some information in this service. Unfortunately, this information (first/last name, email address) is also something we want to use from our application. My normal inclination is to pick one canonical data source and stick with it, but round-tripping to a web service every time I want to look up these fields isn't really a viable option (we use some of them quite a bit), and the service's API requires the records to be stored there, so the duplication is sadly necessary.
But I have no interest in peppering every method throughout our business classes with code to synchronize data to the web service any time they might be updated, and I also don't think my entity should be aware of the service to update itself in a property setter (or whatever else is updating the "truth").
We use NHibernate for all of our DAL needs, and to my mind, this data replication is really a persistence issue - so I've whipped up a PoC implementation using an EventListener (both PostInsert and PostUpdate) that checks, if the entity is of type X, and any of fields [Y..Z] have been changed, update the web service with the new state.
I feel like this is striking a good balance between ensuring that our data is the canonical source and making sure that it gets replicated transparently and minimizing the chances for changes to fall through the cracks and get us into a mismatch situation (not the end of the world if eg. the service is unreachable, we just do a manual batch update later, but for everybody's sanity in the general case, the goal is that we never have to think about it), but my colleagues and I still have a degree of uncomfortableness with this way forward.
Is this a horrid idea that will invite raptors into my database at inopportune times? Is it a totally reasonable thing to do with an EventListener? Is it a serviceable solution to a less-than-ideal situation that we can just make do with and move on forever tainted? If we soldier on down this road, are there any gotchas I should be wary of in the Events pipeline?
In case of unreliable data stores (web service in your case), I would introduce a concept of transactions (operations) and store them in local database, then periodically pull them from DB and execute against the Web Service (other data store).
Something like this:
public class OperationContainer
{
public Operation Operation; //what ever operations you need CRUD, or some specific
public object Data; //your entity, business object or whatever
}
public class MyMailService
{
public SendMail (MailBusinessObject data)
{
DataAcceessLair<MailBusinessObject>.Persist(data);
OperationContainer operation = new OperationContainer(){Operation=insert, Data=data};
DataAcceessLair<OperationContainer>.Persist(operation);
}
}
public class Updater
{
Timer EverySec;
public void OnEverySec()
{
var data = DataAcceessLair<OperationContainer>.GetFirstIn(); //FIFO
var webServiceData = WebServiceData.Converr(data); // do the logic to prepare data for WebService
try
{
new WebService().DoSomething(data);
DataAcceessLair<OperationContainer>.Remove(data);
}
}
}
This is actually pretty close to the concept of smart client - technically not logicaly. Take a look at book: .NET Domain-Driven Design with C#: Problem-Design-Solution, chapter 10. Or take a look at source code from the book, it's pretty close to your situation: http://dddpds.codeplex.com/

WCF service design question

Is it ok from your real-world-experience to define service contract with one method which will accept some object as a form of request and return some other object as a result of that request. What I mean is instead of having method for creating, deleting, editing and searching customers I would have these activities encapsulated within DataContracts and what service would do after receiving such DataContract would be take some action accordingly. But service interface would be simple as that:
interface ISomeService
{
IMessageResult Process(IMessageRequest msg);
}
So IMessageRequest would have filed named OperationType = OperationTypes.CreateCustomer and rest of fields would provide enough information for the service that it could create Customer object or record in database or whatever. And IMessageResult could have field with some code for indication that customer was created or not.
What I'm trying to achieve by such design is an ability to easy delegate IMessageRequest to other internal services that client side wouldn't even know about. Another benefit I see is that if we will have to add some operation on customers we only provide additional DataContract for this operation and don't have to change anything on service interface side (I want to avoid this at all costs, I mean not new operations but changing service interface :)
So, what do you think? Is it good way of handling complicated business processes? What are pitfals, what could be better.
If I duplicated some other thread and there are some answers to my question please provide me with links because I didn't find them.
Short answer: yes, this could be a very good idea (and one I have implemented in one form or another a couple of times).
A good starting point for this type of approach are the posts by Davy Brion on what he calls the request/response layer. He consolidated his initial ideas & thoughts into a very usable OSS project called Agatha, which I am proposing at a customer site as I write this.
This is exactly what we're doing here where I work. It works great and is easy for all the developers to understand, and really easy to wire up new methods/class/etc.