I'm implementing an OData v4 Service with WebApi and I also implemented support for OData Changesets using the code from https://damienbod.wordpress.com/2014/08/14/web-api-odata-v4-batching-part-10/
Basically this is working, but now I'm wonder about the correct behaviour when modifying the same entity from multiple requests in one changeset.
Consider this example:
Content-ID: 1 - POST ~/Entity
-> Create new Entity.
Content-ID: 2 - PUT ~/Entity($Entity-ContentID1)/Company/$ref?$id=URI
-> Create link from new Entity to existing Company using the ContentID.
Content-ID: 3 - POST ~/Entity($Entity-ContentID1)/ChangeState
-> Execute action to change the state of the newly created Entity.
The ChangetState can only be executed, if a Company is linked. If a client sends all requests in this order and if I execute the requests in order, everything is fine.
But according to the OData Spec, requests in a Changesets are unordered.
What is the expected result if a client sends request 3 before request 2? With my current implementation this changeset will fail, but is this really okay?
It's quite hard for me to understand the correct semantic of changesets...
Batch requests are submitted as a single HTTP POST request to the batch endpoint of a service, these requests in a Changeset should be sent to service and proceed in original order.
I think, the spec mean: requests in Changeset will be processed un-order, in our lab, we process with origin order, but different service can use different order, what you concerned is not necessary, client should'n expect same result for a changeset like your scenario, otherwise they should put in different changeset, then the result should be same.
Related
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.
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).
My application uses ASP.NET MVC 5 with OutputCache (in detail, we use MVCDonutCaching) to cache high traffic sites and expensive routes.
Some of the Actions have a Custom ActionFilter which adds a Content-Range header depending on the view model. Without caching it works like charm. When the cache is enabled the first hit is ok (Content-Range header is present in the response) - but the second one only contains Content-Type and the HTML/JSON Response and our custom Content-Range header is missing (which breaks the client functionality).
Is there any way to enable proper header caching without writing an own OutputCache implementation?
Thank you very much.
The cached response is a "304 - Not Modified" HTTP Response, and that kind of response is not expected to return entity headers (except some exceptions like "Last-Modified").
The "Content-Range" header you are trying to return is an entity header:
http://www.freesoft.org/CIE/RFC/2068/178.htm
Here is a full list of Entity headers:
https://www.rfc-editor.org/rfc/rfc2616#section-7.1
The reason why 304 is not returning entity headers is that the 304 response is not supposed to return a full representation of the target resource, since nothing changed.
The 304 (Not Modified) status code indicates that a conditional GET
or HEAD request has been received and would have resulted in a 200
(OK) response if it were not for the fact that the condition has
evaluated to false. In other words, there is no need for the server
to transfer a representation of the target resource because the
request indicates that the client, which made the request
conditional, already has a valid representation;
That means that entity headers should not be transferred again. This ensures consistency, and also has some performance benefits.
If the conditional GET used a strong cache validator (see section 13.3.3), the response SHOULD NOT include other entity-headers. Otherwise (i.e., the conditional GET used a weak validator), the response MUST NOT include other entity-headers; this prevents inconsistencies between cached entity-bodies and updated headers.
https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p4-conditional-23#section-4.1
My conclusion is that ASP.NET and IIS are interpreting this specification correctly, and what you are trying to do is NOT supported. A prove for that is that Apache, and other popular web servers do the same as explained above.
If you still need that header in your 304 you will have to identify and replace (if possible) the components responsible for filtering the 304 responses.
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.