An app makes an HTTP post with Idempotency Key in the API request header.
On the server-side, you want to check if the request with the Idempotent Key has been processed for this client or not.
If the request has not been processed than we proceed with the method to CREATE, UPDATE or DELETE.
If the Idempotent Key has been used in the previous request, then we response back to the client with an error message.
How do we track the API request, the API count, and the Idempotent Key used in request etc?
By logging all API request in the database and make a round trip to the database to check this information everytime a new request is made? Or is there a better way?
You can try to use this open source component on github to solve your problem IdempotentAPI
What I like doing in a fairly standard setup (database, EF core, web api) is use a middleware to add (Context.Add()) the idempotency key to the database without committing.
Later on, in the controller, a service or some sort of handler, I make sure Context.SaveChanges() (or UnitOfWork.Commit()) is called only once (which should normally be the case since you’re supposed to update only 1 aggregate root per transaction).
This way you’re sure you’re saving atomically, your idempotency key will only be saved if your insert/update/delete is successful. If the idempotency key already exists in the database your insert/update/delete will fail.
Finally, what you can also do is cache your successful responses, so that in case of idempotency exception, you can simply return the cached response.
Related
We are implementing OData batch request in our OData endpoint, in order to be able to send multiple operation in single request. So, the one of the reasons of implementing Batch request is to be able to create Invoice and InvoiceDetails in single request. If there is any error or validation message in context, the entire operations should be roll backed(undo all changes).
I have unit test that creates 2 entities in single batch request, first entity with correct value, so it is gets saved to DB, but the second entity has error(or message in context) it will create the message. In response I see first entity is created and the second entity is not. So what should I change to be able to roll back entire request operation and if there is any error it should not save to DB.
I tried with EnableContinueOnErrorHeader and without, but still the first entity gets saved to DB.
config.EnableContinueOnErrorHeader();
Thanks in advance,
It is not uncommon in a RESTful setting for the client to sent an operation id (typically a GUID) so that the request logs can be traced.
My question is, in Web API, is there a way native to .NET Web API to track the id per request?
log4net has LogicalContext that could track that. The problem with LogicalContext is that it is specific to log4net and cannot be used with NLog. There is no way in LogicalContext to get the list of all keys. I have to know the key before hand, which cases a problem if one API calls it "operation id" and another API calls it "activity id".
Maybe use the Guid 'Trace.CorrelationManager.ActivityId' for CorrelationId ?
It can be configured per request in your application-class (inherits from System.Web.HttpApplication) using the method Application_BeginRequest.
https://github.com/NLog/NLog/wiki/Trace-Activity-Id-Layout-Renderer
I'm implementing a RESTful API for a DVD rental website using ASP.NET Web API. The domain model (simplified) consists of Customer and Subscription entities. A customer has an associated subscription.
Most of the operations exposed by the API are simple CRUD operations, which are easy enough to model according to RESTful principles. E.g.
GET /api/subscriptions/1 - get subscription with id 1
POST /api/subscriptions - add a new subscription
PUT /api/customers/2 - update customer with id 2 with contents of PUT body
There is a requirement to periodically check for expired subscriptions, by comparing the EndDate field on each Subscription entity read from our database with the current date. For each subscription that has expired, the CustomerStatus field of the associated customer should be set to Archived and an email sent to the customer. The operation will be exposed through our REST API and invoked daily from an external service.
What URL scheme should I use to expose this operation according to RESTful principles? My first thought is that it's a PUT operation on api/customers/{SomeResource} as it potentially involves updating the CustomerStatus field of zero or more customers and is also an idempotent operation.
For example:
PUT /api/customers/expired
Does this sound reasonable?
Note that there is no body sent in this request, as the customers whose statues are being updated are queried from a database rather than being supplied by the end user. My understanding is that a PUT request doesn't have to include a body.
This is almost certainly a POST operation.
However, I question the design of your service. Why does the behaviour you describe need to be externally-controlled by way of a RESTful API? If the exact timing and nature of the operation is known beforehand, why not use some other means of scheduling the job...a means that is more straightforward and wouldn't raise these kinds of questions?
Ref: Stack Overflow
Edit: note that the operation described by the OP is not idempotent and thus not a qualifying PUT operation.
Additional edit: note that the .Net framework uses the POST method by default for service endpoints marked with the WebInvoke attribute. Per the documentation for this attribute, it represents an endpoint that "is logically an invoke operation". To me, this reads like a remote procedure call (i.e. RPC).
I want to know what is the best way to avoid the reinsertion of data in ASP.net.
I am currently doing
Response.Redirect('PageURL');
Thanks in Advance
Don't put your insertion code in the Page_Load method, or if you are, make sure you are checking Page.IsPostBack first.
Yes, normally we have an identity autoincrement number id, wich should be sent back to your form after the insertion. So you just have to check on server if that number is > 0 and execute an update instead of an insert.
Your redirect solution is valid. This pattern is called Post/Redirect/Get.
Post/Redirect/Get (PRG) is a web development design pattern that
prevents some duplicate form submissions, creating a more intuitive
interface for user agents (users). PRG implements bookmarks and the
refresh button in a predictable way that does not create duplicate
form submissions.
When a web form is submitted to a server through an HTTP POST request,
a web user that attempts to refresh the server response in certain
user agents can cause the contents of the original HTTP POST request
to be resubmitted, possibly causing undesired results, such as a
duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] —
instead of returning a web page directly, the POST operation returns a
redirection command. The HTTP 1.1 specification introduced the HTTP
303 ("See other") response code to ensure that in this situation, the
web user's browser can safely refresh the server response without
causing the initial HTTP POST request to be resubmitted. However most
common commercial applications in use today (new and old alike) still
continue to issue HTTP 302 ("Found") responses in these situations.
Use of HTTP 301 ("Moved permanently") is usually avoided because
HTTP-1.1-compliant browsers do not convert the method to GET after
receiving HTTP 301, as is more commonly done for HTTP 302.[2] However,
HTTP 301 may be preferred in cases where it is not desirable for POST
parameters to be converted to GET parameters and thus be recorded in
logs.
http://en.wikipedia.org/wiki/Post/Redirect/Get
I've got several web-services: asmx,wcf. At couple of them there are some methods, which take a lot of time for processing, but size of input data for these methods are small and it takes not much time to transfer on the wire. I want move to not sync model. Client passes data to service, service answers that data transfer was correct and process it at background thread witout connection with client. So agter transfering connection should be closed. IS it possible? Can u help me with articles or may be just google request.
John is right - Once you close an http connection, it is done. You can't get back to the same process.
So if you can use another technology that allows duplex on one connection (e.g. WCF), do it!
However,
if you have no choice but to use webservices,
here are three ways to make it work. You may get timeouts on any of them.
Option 1:
Forget the part about 'client answers data was correct.' Just have each thread make its request and wait for the data.
Option 2:
Now, assuming that won't work and you must do the validation, this way requires the client to make 2 requests.
First request: returns valid/invalid.
Second request: returns the long-running results.
Variation of option 2:
If you have timeout problems, you could have the first request generate a GUID or unique database key and start another process, passing it this key, and return the key to the client. (if you can get the server to allow you to start a process - depends on security settings/needs - if not you may be able to start an async thread and have it keep running after the websvc one ends?) The process will do the long task, update the row in the database w/ the unique id when finished, revealing the results plus a 'done' flag. The second request by the client could always return immediately and if the processing is not done, return that, if it is, return the results. The client will repeat this every 5 sec or so until done.
Hacks, I know, but we don't always have a choice for the technology we use.
Don't do this with ASMX web services. They weren't designed for that. If you must do it with ASMX, then have the ASMX pass the data off to a Windows Service that will do the actual work, in the background.
This is more practical with WCF.
We have been writing stuff to interact with the UK gov website and the way they handle something similar is that you send your request and data to the server and it responds saying, roughly, "thanks very much - we're processing it now, please call back later using this id" - all in an XML message. You then, at some point later, send a new http request to the service saying, essentially, "I'm enquiring about the status of this particular request id" and the server returns a result that says either it has processed OK, or processed with errors, or is still processing, please try again in xx seconds.
Similar to option 2 described previously.
It's a polling solution rather than a callback or 2 way conversation but it seems to work.
The server will need to keep, or have access to, some form of persistent table or log for each request state - it can contain eg, the id, the original request, current stage through the workflow, any error messages so far, the result (if any) etc. And the web service should probably have passed the bulk of the request off to a separate Windows service as already mentioned.