We are designing a system which needs to allow the construction of objects made up of data, sourced from disparate datasources (databases, and back office systems for example) and are looking at ways to facilitate this functionality across a web service interface.
To service this requirement we propose creating a "request" object as an input parameter for the web service request methods so the web service knows which fields on the object to populate from which source, a sort of "pick n mix" to poulate your return object.
How could this "Request template" object be designed and is it a suitable approach?
We need the solution to achieve the following:
Must be clear to the consumer of the
service what the method expects and
what will be returned.
The Consumer must have visibility as
to what locations are available for
each field when constructing the
request.
A clear relationship between the
response object and the request
object exists.
Have you considered using WCF and have the request object use an interface, that way it is extensible as well?
Related
I'm working on a project that is our companies first foray into Domain Driven Development.
Our Web API originally simply provided CRUD operations and the project exposed OData controllers, but I'm not sure if that is still a good idea.
Is OData a good way to expose non-CRUD APIs?
More info:
Initially our web api basically exposed CRUD functions. To create a new User you would simply create one and post it to the service. To change, for example, an address you would get a copy of the user entity, make changes, then perform an update operation. Basic OData stuff.
Beyond providing query support, OData also exposed the service in a readily consumable way, so it could be added to other projects as a service reference and accessed with a proxy.
Since we have moved over to a DDD approach, things have changed significantly. Our Web API is now simply a gateway to a number of independent sub-domain services. We no longer provide CRUD operations or direct access to entities, instead making service calls to manipulate entities. Instead of creating a User entity sending it to the User service via a Put request, a consumer must generate a CreateUserBindingModel and send it to the User/Create service and let the service generate the entity. Changing an address is done through the ChangeAddress(ChangeAddressBindingModel model) method, rather than just updating the whole object. Queries are much more targeted and rarely if ever return entire domain objects.
Is it a bad idea to keep using OData as a basis for our Web API, when we no longer provide CRUD operations? Is there another way to expose the details of our service the way you can with OData? I know WCF services provide similar functionality, but I was under the impression it was even more tied to CRUD than OData.
OData is a data oriented API spec, it's anti-DDD. Although it can satisfy all your requirements to implement REST APIs but it's best for data processing API. I guess you already know that using OData feels like operating the database via HTTP. If you are using DDD you should forget OData totally.
In OData, actions and functions are a way to add server-side behaviors that are not easily defined as CRUD operations on entities
https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions
https://blogs.msdn.microsoft.com/alexj/2012/02/03/cqrs-with-odata-and-actions/
https://github.com/OData/ODataSamples/blob/master/WebApiCore/ODataActionSample/ODataActionSample/
The reason why I need loosely-coupled WCF because Entity Framework is tightly-coupled. When I say loosely-coupled, there's no need to instantiate the database context or add the service reference of WCF. It just rely on web configuration or some .ini file that does not require compilation when developers need to change servers, ip address or service url's.
Instead, the MVC(say controller) will just send request message and then gets the response data from WCF service. But still we cannot afford without having Models based on the database (since we need it in intellisense for views markup), where the WCF will get the data. Let say we have those database objects class already, create some repository that binds the WCF data to the MVC Models.
What I mean of WCF web service, it ONLY contains messages, no more passing of object reference, because thats the new SOA definition. It makes more sense to pass messages instead of objects.
Is this a better approach? In terms of scalability and performance, I don't mean to offend the Entity Framework Fans.
It is an entirely valid approach to define a WCF web service in terms of message schemas which just use basic types, so that clients need know nothing about WCF in order to use the service. WCF would be useless for interop with other platforms (e.g. Java) otherwise.
Understand that WCF is a general and powerful framework for implementing communication over a variety of transport protocols. It can be equally effectively used for raw XML messaging as for programming in terms of objects. Object serialisation and deserialisation is an optional extra of the framework, not a requirement. (There is really no such thing as "passing of object reference" - ultimately it is an XML infoset which travels across the communication channel. Also, Entity Framework is not part of WCF - it is a distinct ORM Framework which you can use with WCF if you want, but that's your choice.)
Scalability and performance is entirely orthogonal to the design of the service in terms of its data and operation contracts. You should feel free to adopt whatever approach to defining your services is best for your application. If that's XML messages, that's fine - don't let anyone tell you otherwise.
From .NET(C#) code, we are invoking a Java Web Service.
Its a SAOP request. The Java WebServices are developed using Axis 1.4.
Following is the sample code that makes the java web service request:
private string GetUserInfo(string strEID)
{
string strEmpData = string.Empty;
GetEmpInfo.EmpProxyService objEmp;
try
{
objEmp = new GetEmpInfo.EmpProxyService();
strEmpData = objEmp.searchByEID(strEID);
}
catch (WebException ex)
{
}
objEmp.Dispose();
return strEmpData;
}
Now, we have a change request which requires passing some additional information - a name_value pair to the java webservice.
How can we achieve this ?
Can I pass the information in HTTP/SOAP headers?
Changing the method signature and adding the additional info to pass the info is not at all the good idea I guess.
EDIT: Its basically we want to add the logging inforamtion of who are all consuming the web services. Once the java webservice request is processed successfully, we will log the usage information along with the source of the request (from webappln/windows appln/flex client).
We want the clients to send its unique id to identify it. Since this has nothing to do with the business logic, can we add it meta-data info...say in headers.
If you have control over the service signature, I would actually suggest that you change the signature of this web service, or add another method that takes the additional arguments. When you're using a high-level language like C# or Java, the tendency is for the web service framework to abstract the entire SOAP stack away from you, and leaves you dealing with just the plain objects that eventually get serialized to make the method call. With only the argument objects exposed, it can be tricky to try to inject additional stuff into the SOAP message, if it's not part of the actual method signature.
There are usually ways to manipulate the SOAP message by hand, but I would probably shy away from that if possible, as editing the SOAP message by hand goes against the point of using a serialization-driven framework. That said, if you have no control over the service method, and the group in control of it needs you to pass additional data outside of the soap objects, you might be stuck messing with the SOAP message by hand.
If you want to add some future proofing to your services, I would suggest passing a full-fledged object rather than a single string or primitive value. In your object, you could include a key-value data store like a HashMap or Dictionary so that additional data can be passed without changing the signature or schema of the web service. With key-value data, documentation becomes important because it's no longer clearly specified data types or parameters.
You can use SOAP headers but I would rather not go that route since the headers have no business meaning. Rather change the signature and use request and response objects.
SearchByEIDResponse GetEmpInfo.EmpProxyService.searchByEID(SearchByEIDRequest)
Ths makes any changes less painfull and prevents huge parameter lists.
How you pass information to a web service is dependent on the methods that web service exposes. What language that service is written in is inconsequential to you as the consumer. IF the Java web service requires a name value pair to retrieve some data than a method signature will expose that.
objEmp.searchByEID(strEID, strVal1, strVal2);
That said you as Eben indicates you are better off using request and response objects to keep your parameter lists short. When to use these more complex types comes with experience i.e. don't use a request object from the get go if you need to only pass a single string value, but use a request object if you need to pass 50 string values.
If you have multiple webservices and don't want to change all methods (which is reasonable), a SoapExtension is the way to go http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx
You write your soap extension class on the client, declare it in the web.config and you're done.
I've been asked to come up with a .net web service stub for multiple similar webservices which will:
implement create/read/update/delete/find for an arbitrary object.
hold persistent xml data for objects of that type.
Is there anything out there that does this job already or anything that can make the job of creating it easier?
You may look at WCF Data Services. As usual with Microsoft products it is impossible to understand what it really does by looking at the front page, but is something of a "query a database by specifying the query in the URL in a standardized format (OData)". It creates a WCF service as a front end, and you should be able to write your own dataprovider for XML files.
It is arbitrary in the sense that the technology is independent of the object type, but you need to create a schema for its specific datatypes.
I have an asp.net MVC2 application that needs to call a web service from the controller. How do I do this? It is a RESTful service that returns Json data.
I cant seem to find a good example.
Thanks
You call it the same way you would do in any ASP.net application, it is not connected to MVC at all.
Either add a reference and use that (easiest) or go with the manual method: here is a guide, see at towards the end (fig. 14 in particular) for consuming such services:
http://msdn.microsoft.com/en-us/magazine/dd943053.aspx
I have written my own ActictiveResource client framework, which allows the consumer to specifiy the http provider and the serialisation provider. The generic activeResource class has the four main verbs (get,put,post,delete) as methods which it calls against a specified resource url, passed in at cunstruction. the fololwing is an example of getting a product item from teh service:
ActiveResource<Product> arProduct = new ActiveResource<Product>(jsoSerializer,liveHttpProv,"https://company/product/1452");
//Get verb
Product prod = arProduct.Get();
Of course you can also use the other verbs on the object to put, post and delete.
arProduct.Post(prod);
The code, basically, wraps up the underlying http post,put, get functions and takes care of the serialiasation of the payload to objects. It has been a very useful component which I have used over and over again. The code can be easily called from a controller, it may be worth using a IOC container (I am using Th eUnity block) to instatiate you providers
Hope this helps
I would put together a simple class that acts as a "client" that makes a web-request from the URL, and then return the response as a string.
From there you can deserialize the JSON data using either the JSON serialization that ships with WCF, or the most excellent JSON.Net library. You will need to create a simple data class that is structured in the same way as the JSON data your expecting back.
You could also combine the two and have your client class return the deserialized object directly.