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.
Related
Is it recommended practice to implement the below endpoint using 'PUT' verb to create & update a resource?
PUT/jobs/{jobid}
(or)
POST/jobs - to create resource
PUT/jobs/{jobid} - only to update the existing record
Mixing up create & update logic in PUT endpoint may create issue in the endpoint consumer side as PUT is idempotent while POST is NOT idempotent.
What are the other consequences if I mix up create & update resource logic with in 'PUT' endpoint?
Point me to any relevant RFCs, if any.
The HTTP PUT verb is used to update a resource, but it can also be used to create a resource if the resource does not already exist, but it's bad practise as it goes against its meaning.
POST is not idempotent, while PUT is idempotent. This means that multiple identical POST requests may create multiple resources, while multiple identical PUT requests should update the same resource each time.
If you want to support both creating and updating a resource using the same endpoint, you can use the POST verb for both operations and include an additional parameter or field in the request to indicate whether you are creating or updating the resource.
you can refer to the HTTP 1.1 specification (RFC 7231): https://tools.ietf.org/html/rfc7231#section-4.3
Mixing up create & update logic in PUT endpoint may create issue in the endpoint consumer side as PUT is idempotent while POST is NOT idempotent.
It shouldn't introduce any client issues.
An important constraint in REST is the uniform interface, which means (among other things) that everybody understands message semantics the same way. In the context of HTTP, that means that everybody agrees that HTTP PUT means... whatever the current standard says it means.
The current registered reference for HTTP PUT is RFC 9110:
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message content.
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
In other words, PUT is a lot like "save file"; it's the HTTP method we would use if we were using HTTP to publish a new page to our website.
The uniform interface constraint tells us that our HTTP APIs should understand messages exactly the same way that a general purpose web server would understand them.
The power that gives us is that it allows us to use general purpose components (browsers, caches, proxies) without needing to know anything about the semantics of the resource or its representation.
(Note: the important thing to recognize is agreeing on what the messages mean doesn't mean that the server needs to do a specific thing. See Fielding 2002 on the semantic constraints of HTTP GET; the principle is general to all standardized HTTP methods).
Now, you can use HTTP POST if you prefer (see Fielding, 2009). The problem is that POST semantics allow a lot more freedom, which restricts a general purpose component from doing intelligent things because it doesn't know enough about what is going on.
For example, on an unreliable network an HTTP response may be delayed or lost. Because the semantics of PUT describe an idempotent action, general purpose clients can know that it is safe to try sending the request again. POST, on the other hand, doesn't imply that constraint, and therefore general purpose components shouldn't automatically retry those requests.
But it's a trade off - POST limits what a general purpose component can do in response to a contingency, but maybe it is worth it if that means your API is more familiar to the human developers who are going to use it, or if it makes life easier for the operators keeping your API running, or whatever.
if PUT can create or update a record then how it should be idempotent?
Because idempotent, in HTTP means:
the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
It's a lot like how we use maps/dictionaries/associative-arrays to store information
dict["readme.txt"] = "Hello World"
and
dict["readme.txt"] = "Hello World"
dict["readme.txt"] = "Hello World"
dict["readme.txt"] = "Hello World"
Call it once, call it twice, call it thrice, the end result is the same: we have this specific value stored under this specific key.
That's really what PUT means; the target URI is the key, the request body is the value. "Please make your document look like my document".
I have an existing WCF service and I use Channelfactory to get the proxy and call the service. Now I have a new requirement to return a custom data for all of my calls. And I dont like the idea of changing the return type to accommodate this new data.
What is the best option I have ? What about sending the data in a custom header?
The function which will use the proxy is in a separate library from where it is created. I prefer this library where proxy is used to have minimal dependency to WCF
You can return a dynamic type or HttpResponseMessage. If you use HttpResponseMessage then you can return the status also.
Request.CreateResponse(HttpStatusCode.OK, {response object here});
I've done this with custom headers before. It's nice because it's appended to every single call, automatically, without needing to change anything else. This was in place of modifying every single call to contain this information.
Here is a good tutorial on how to add custom message headers. (It isn't nearly as complicated as it looks)
I'm trying to send objects which are serialised as JSON to my WCF service. The thing is, though, some of the data from my android isn't needed on the service side, so I didn't add the attributes. I was wondering how I'd be able to have it so it can lack the attributes but still receive it?
So, in my android, I have JSON like this {"buiildings":{"id":1, "name":"boob", "otherThing":"Ya"}} and my Building object in WCF only has the id and name as attributes, so it only expects them. Can I have it so it just ignores the other attribute?
Yes, You can pass as many as extra attribute in JSON object. it will not give any error at WCF side. but you are not able to use these extra attribute as it is not define in Building object in WCF.
But i suggest do not to pass extra attribute because it will increase request size, and cause effect on performance.
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?
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.