This question is about “informational messages” and having them flow from a “back end” to a “front end” in a consistent manner. The quick question is “how do you do it”?
Background:
Web application using WCF to call back end services.
In the back end service a “message” may occur. Now, the reason for this “message” may be a number of reasons, but for this discussion let’s assume that a piece of data was looked at and it was determined that the caller should be given back some information regarding it.
This “informational” message may occur during a save and also may occur during retrieval of information. Again, the message is not what is important here, but the fact that there is some informational messages to give back under a number of different scenarios.
From a team perspective we all want to return these “messages” in a standard way all of the time. Now, in the past this “standard way” has been done different ways by different people.
Here are some possibilities:
1) Every operation has a “ref” parameter at the end that contains these messages
2) Every method returns these messages… however, this only kind of works for “Save” methods as one would think that “Retrieve” methods should return actual data and not messages
3) Some approach using the call context so as to not "pollute" all message signatures with something; however, with WCF in the picture this complicates things. That is, going back to the messages go on a header?
Question:
Back to my question then… how are others returning “messages” such as what was described above back through tiers of an application, over WCF and back to the caller?
I think you basically have two proper ways of doing this:
add a InfoMessage : string field to all your DataContracts, which can hold an informational message (or not) back from the server
If you don't want to put that into the DataContracts, then create a header which you populate on the server before the message goes back to the client, and on the client, you can inspect that header and retrieve it if present
In order to automagically add headers to WCF messages, typically the mechanism of MessageInspectors is used - little chunks of code that can be configured or added by means of an attribute on your operation contract, that will add the header on the one end, and inspect the incoming message for that header (and extract it, if present) on the other end.
There are a number of pretty good blog post out there showing you how to create a message inspector:
Richard Hallgren's WCF postings
Writing a WCF message inspector
Automatic Culture Flowing with WCF by using Custom Behaviour
Those mostly go from client to server, e.g. the client sends along a header with some "meta-information" for the service - but it works just fine the other way around, too.
Check out the two relevant interfaces to implement:
IClientMessageInspector on the client side, which has a BeforeSendRequest and AfterReceiveReply message to implement
IDispatchMessageInspector on the server side, which has a AfterReceiveRequest and BeforeSendReply method to implement
Related
I have one scenario, Let Say A is a Web based Application and needs to show some data on screen based on data returned from component B.
Now A send some data(which is going to be input parameter for a component B) on an event to B , and component B is going to do calculation on input parameter and return data to A.
Both A and B are handled by different organization, So what is the best way to communicate between them, is WCF or WEB API(also suggest how can we implement this scenario)?
I am thinking of creating Web API for component B here , so that A can consume that and call component B,and Transfer data in JSON format.
But the issue in this approach is that, this request is going to be GET Request, and we can't send complex types on GET request. Even if we are communicating through JSON format, how can we send huge data in GET request.Please correct me if mine understanding is wrong.
No of Input Parameter is ranging between 10 to 20 and number of request made to Component B is very much frequent, So we have to take care of performance as well.
Updatde 1: First Issue is we can't send data in Request Body for GET.
Generally the question is WCF for complexity and security vs WebApi for simplicity and speed. If WCF features are not required, I will go for WebApi. If you need to send complex data with request, you can use POST.
It is perfectly correct to request data using POST, there are only small limitations.
Look here: https://www.w3schools.com/jquery/jquery_ajax_get_post.asp
I'm relatively new to WCF services, so I apologize in advance if I'm missing the obvious. My business uses EasyPost as our shipping solution, and I've written a WCF service to handle the shipping status webhook calls from EasyPost, described here: https://www.easypost.com/docs/webhooks
Briefly, EasyPost sends an update object as JSON via POST. The problem is that it sends several different types of (non-configurable) updates to the same service method, and I'm finding it difficult to write a DataContract that encompasses all the possibilities. For example, if the argument it sends is a tracking number update, update.result.status will be a string value; if it's a batch status update, update.result.status will be an object. It's a bit of a mess.
I tried handling just the update type that I care about and returning a 400 status code on the others, but EasyPost interprets that as an outage and drops my service as a webhook endpoint.
From what I've read, it looks like I could abandon the comforts of a Data Contract in favor of using a System.ServiceModel.Channels.Message parameter as a catch-all, then parse the message manually. That doesn't strike me as a wise/clean solution, though.
I'd be grateful for any alternatives.
This is probably not the best way I could have handled this, but it works.
I have an HTTP Module that identifies whether the incoming request is for the proper service method, and if so, converts the ContentType header from "application/json" to "text/plain".
My service method accepts the content body as a System.IO.Stream parameter. By converting the stream to a byte[] and then to a string, I end up with the raw JSON string sent by EasyPost.
After that, it's just a matter of using Newtonsoft.Json to attempt to deserialize the JSON string into the expected Type.
Even if the deserialization fails, I can still log the data and send a success response to the caller. That's good enough for my purposes.
I'm designing a web service and a desktop client application that uses the web service. The interface has a requirement that you need to be able to perform multiple operations and commit them all at once. The operations are basic CRUD operations (create, read, update, delete).
Here's a rough, and Car-ified example of what the workflow would be:
The problem is that the service calls could be spread out over time. I originally had created a REST web service, but REST by definition shouldn't be transactional. The interface has to be able to commit all operations to the database in one go (upon a Save button click).
Edit: An important stipulation is that given the example above, a Car must exist in the database on the server in order to add seats to it. Within a transaction, that car should only be available to the person (session) who is working within that transaction. That limits the ability to send all the operations to the web service at one time at the end of the workflow.
The options I have considered so far are:
1) Implement distributed transactions using SOAP (WCF) and only commit when Save is clicked on the GUI. Is this possible/a good idea for longer transaction lifetimes?
2) Create a unit of work 'service' that takes operations and executes them all within one transaction on the server.
My question is, is 1) possible, or a good/bad idea? Is 2) a good idea, and are there any patterns/tools for implementing this across a web service (REST or SOAP)? Or is there a different way to handle this problem?
I would try this:
POST /unit-of-work
create with response 200
POST /car
create with response 202
POST /seat
create with response 202
etc.
PUT /unit-of-work
set "execute" bit, or somesuch
In this case, car, seat, etc have the unit-of-work specified when they're posted. When the unit-of-work is updated to be "done", all the items are executed.
Another approach would be:
POST /car
create with response 202
POST /seat
create with response 202
etc.
POST /unit-of-work response 200
In this case, car, seat, etc have a bit set saying they're not created yet. The unit-of-work should specify what resources belong to it, and then the back end can flip the bit on the other resources so they're created.
I have a class library I developed that is rather processing intensive that I currently call through a WCF REST service.
The REST service directly accesses the DLLs for the class library and more or less the WCF rest service is an interface for the system.
Let's say the following methods are defined:
Create Request
Starts a thread that takes five minutes, but immediately returns a session ID that the process generates and the thread uses to report when it is completed to the database.
Check Status
Accepts a session id and checks the database to see if the process has completed.
I have to think that there is a better way to "manage" the threads running, however, my requirements state that the user should receive an immediate response from the REST service upon issuing a request.
I am using the WCF Message property to return XML to the browser and as this application can be called from any programming language I can't use classic WCF and callbacks (I think, correct me if I am wrong).
Sometimes I run into an issue where an error occurs and the iscomplete event never gets written to the database and therefore the "Check Status" method says it's processing forever.
Does anyone have any ideas about what is normally done and what can be done in this situation?
Thanks!
Jeffrey Kevin Pry
Your service should return a 202 Accepted at the initial request with a way for the client to check the current status, either through the Location header or as part of the content.
As you indicate the client then polls the URL indicated to check the current status. I would also suggest adding a bit of cache time to this response in case a client just starts looping.
How you handle things on the server is up to you and in no way related to REST. For one thing I would put all logic that executes as the background thread in a try/catch to you can return an error status back if an error occurs and possibly retry the action depending on the circumstances.
I implemented a similiar process for importing/processing of large files and to be honest, I have never had a problem. Perhaps resolving the reason that the IsComplete never gets set will make this more resilient.
Not much of an answer, but still..
My applciation works as follows
[user]----username/password/domain----->[WCF service]
then i access the domain server to see to which actual DB the user is associated,
after getting that, i validate the user in his actual DB(DB is per domain)
the problem is that i need a place to store the domain name for the following requests against the db.
for example,if the users calls a WCF service operation:
Test()
first the validation procedure is called, (WCF UserNamePasswordValidator) which validates the user password(which is sent as part of the header for REST or as part of the SOAP), and the next function to be called is the Test, but by then i cant tell the domain of the user(to actually serve the request agains that domain..)
I dont want to change the signature of each domain to
Test(string domain)
I cant simply access the headers since i expose the same methods both as REST and as SOAP and the authentication is different for each of them..(one is with headers as with Amazon S3 and the later is using the SOAP standard)
so basically i'm looking for a global, per call storage.(i want to avoid the Per-Call initiation method)
thanks.
EDIT:
Maybe i should use the ThreadStaticAttribute? will that work?
This will not work. You can't store anything in UserNamePasswordValidator. It even doesn't have access to OperationContext because it runs on different thread.
The way to do this is create custom message inspector and extract the information from custom message header to custom operation context extension as Frank mentioned.
WCF knows a Current OperationContext. You can write your own extensions for it. Unrelated to this issue, I used the same mechanics in this NHibernate Session management here, which may work in its concept for you as well. It accesses the InstanceContext, but the concepts are similar.