I am new developer and i have not much knowledge on http service. so i was finding the difference between PUT and POST. i read this one https://forums.asp.net/t/2100831.aspx?WebApi+what+is+difference+between+PUT+and+POST
below things not clear specially what is idempotent?
i found one guy said - The PUT method is defined to be idempotent ( ie : have the same result over subsequent calls ). PUT would always update the same resource and return 200 status code.
But POST would create a new resource and return 201 status code.
anyone would mind to explain why PUT is considered as idempotent. thanks
From a pure RESTful point of view PUT is considered idempotent because it does not matter how many times you make the same request, the result will be the same.
However, this being said, don't forget that the object you are trying to update might have its state changed between these identical PUT requests so the response you get might not actually be the same.
This does not mean that if you fire 100 PUT requests only one goes through though like in a previous response.
One more thing, just to be clear, POST is used to create new resources and typically returns the unique identifier of the created resource.
PUT is used to update resources and typically returns the entire updated resource so you can see what changes have been made to it.
There have been many discussions on what data should each of these accept, my personal view is that POST takes the fields required create the resource, no ID, while PUT takes the fields take will be updated and if the ID is part of the URL then it can be omitted again
for example, let's say you issue a PUT request to an endpoint like this:
api/users/1
where 1 is the id you need to identify this user, then your method could look like this:
[HttpPut]
public UserClass Put(int id, UserClass user)
{}
in this case your UserClass does not need the id as you already have it from the URL.
Hope all of this makes sense, I find the use of "idempotent" in a RESTful context quite confusing!
Let's say you want to update an User object so you call the PutUser method this way
$.ajax({
url: "yourUrl/PutUser/1",
type: 'PUT',
data: "firstName: fName, lastName: lName",
success: function(data) {
alert('User Updated.');
}
});
And your PutUser method looks like this
[HttpPut]
public dynamic PutUser(int id, UserClass user)
{}
In this case if you make the Ajax PUT request using the same parameters 1, 2..5 or N times the result will be identical, that is what idempotent means.
On the other hand if you have this
$.ajax({
url: "yourUrl/PostUser",
type: 'POST',
data: "firstName: fName, lastName: lName",
success: function(data) {
alert('User Updated.');
}
});
And your PostUser method looks like this
[HttpPost]
public dynamic PostUser(UserClass user)
{}
And call the PostUser method with the same parameters N times, you will Post N identical users and that could mean for example in 100 identical rows in your database, so all your calls will be processed.
Related
What are the fundamental differences of those functions? All I know is all three result in a 201, which is appropriate for a successful POST request.
I only follow examples I see online, but they don't really explain why they're doing what they're doing.
We're supposed to provide a name for our GET (1 record by id):
[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
return new ObjectResult(new MyStuff(id));
}
What is the purpose of naming this get function, besides that it's "probably" required for the POST function below:
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}
I notice that CreatedAtRoute also has an overload that does not take in the route name.
There is also CreatedAtAction that takes in similar parameters. Why does this variant exist?
There is also Created which expects a URL and the object we want to return. Can I just use this variant and provide a bogus URL and return the object I want and get it done and over with?
I'm not sure why there are so many variants just to be able to return a 201 to the client. In most cases, all I want to do is to return the "app-assigned" (most likely from a database) unique id or a version of my entity that has minimal information.
I think that ultimately, a 201 response "should" create a location header which has the URL of the newly-created resource, which I believe all 3 and their overloads end up doing. Why should I always return a location header? My JavaScript clients, native mobile, and desktop apps never use it. If I issue an HTTP POST, for example, to create billing statements and send them out to users, what would such a location URL be? (My apologies for not digging deeper into the history of the Internet to find an answer for this.)
Why create names for actions and routes? What's the difference between action names and route names?
I'm confused about this, so I resorted to returning the Ok(), which returns 200, which is inappropriate for POST.
There's a few different questions here which should probably be split out, but I think this covers the bulk of your issues.
Why create names for actions and routes? What's the difference between action names and route names?
First of all, actions and routes are very different.
An Action lives on a controller. A route specifies a complete end point that consists of a Controller, and Action and potentially additional other route parameters.
You can give a name to a route, which allows you to reference it in your application. for example
routes.MapRoute(
name: "MyRouteName",
url: "SomePrefix/{action}/{id}",
defaults: new { controller = "Section", action = "Index" }
);
The reason for action names are covered in this question: Purpose of ActionName
It allows you to start your action with a number or include any character that .net does not allow in an identifier. - The most common reason is it allows you have two Actions with the same signature (see the GET/POST Delete actions of any scaffolded controller)
What are the fundamental differences of those functions?
These 3 functions all perform essentially the same function - returning a 201 Created response, with a Location header pointing to the url for the newly created response, and the object itself in the body. The url should be the url at which a GET request would return the object url. This would be considered the 'Correct' behaviour in a RESTful system.
For the example Post code in your question, you would actually want to use CreatedAtAction.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff);
}
Assuming you have the default route configured, this will add a Location header pointing to the MyStuff action on the same controller.
If you wanted the location url to point to a specific route (as we defined earlier, you could use e.g.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}
Can I just use this variant and provide a bogus URL and return the object I want and get it done and over with?
If you really don't want to use a CreatedResult, you can use a simple StatusCodeResult, which will return a 201, without the Location Header or body.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return StatusCode(201);
}
I believe there is an example for you here.
Remembering that I'm using .NET 6
[HttpPost]
public IActionResult CadastrarCerveja([FromBody] Cerveja cerveja)
{
using (var ctx = new CervejaContext())
{
ctx.Cervejas.Add(cerveja);
ctx.SaveChanges();
}
return CreatedAtAction(
nameof(LerCerveja),
new { IdCerveja = cerveja.Id },
cerveja);
}
[HttpGet("{IdCerveja}")]
public IActionResult LerCerveja(int IdCerveja)
{
var ctx = new CervejaContext();
var cerv = ctx.Cervejas.FirstOrDefault(c => c.Id == IdCerveja);
if (cerv == null)
return NotFound();
else
return Ok(cerv);
}
I have a VB Web API app.
I have a VB class/model like so.
Imports System.ComponentModel.DataAnnotations
Imports System.Web.Http
Public Class MSLDestinationInput
<HttpBindRequired>
<Required>
Public Property ShpmntCntrlNbr() As String
Get
Return m_ShpmntCntrlNbr
End Get
Set(value As String)
m_ShpmntCntrlNbr = value
End Set
End Property
Private m_ShpmntCntrlNbr As String
End Class
This is the controller:
Public Async Function GeneratePDF(data As MSLDestinationInput) As Task(Of IHttpActionResult)
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
Dim oMSLOutput As New MSLOutput
oMSLOutput.url = "api/PrintGenerateMSL"
Return Ok(oMSLOutput)
End Function
I am posting to the controller using jQuery.ajax with this parameters:
url: 'api/PrintGenerateMSL',
data: ko.toJSON(self),
type: "POST",
and everything is working well. However I don't really need to send the entire knockout model. I just need to send some of the properties. I've tried to send this data:
data: {ShpmntCntrlNbr : self.ShpmntCntrlNbr() };
instead of ko.toJSON(self). When the request reaches my controller, I find the parmeter data is empty.
How can I send only the required data to my controller instead of the whole ko view model?
You need to stringify the data. One way to do it is by using JSON.stringify, as you've done.
Most, but not all browsers, include the JSON manipulation functions. The problem is that if someones tries to use your application in a browser that doesn't have this methods, it will crash. Or you'll have to suplly a polyfill.
The good news is that you don't need to worry about it if you use ko.toJSON. In fact ko.toJSON does two things:
unwraps all the observables, if they exist
convert to JSON, by using JSON.stringify
That means that both of this options would work fine:
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr() })
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr })
Note that the property on the second one would be automatically unwrapped. If you took a piece of your viewmodel which is an object tree that includes some observable properties at any level, ko would also unwrap them automatically.
And, best of all, if the browser does not implement JSON.stringify, ko provieds its own implementation.
yes stringify took care of it. it is working now with.
data: JSON.stringify({ShpmntCntrlNbr : self.ShpmntCntrlNbr() }),
I'm working on an Ember.js app. I have an update function, part of an ObjectController.
The function should save my updated model, however when I call save(); it sends a POST request not a PUT request. (Tested in Chrome.)
Why would that happen? How can I make sure a PUT request is sent for updates?
Here is my code:
customer = this.get('model');
customer.set('name', 'New name');
customer.save();
For extra reference, when I log the "dirtyType" with console.log( customer.get('dirtyType') ); it says "updated".
Any help very much appreciated!
UPDATE
I've adjusted the sample code above to make it clearer, I am NOT creating a new model and wanting to use PUT. I have an existing model that I need to update.
I'm not sure if your workaround is correct in the land of PUT vs POST.
TL;DR PUT should define the resource (by Request-URI), but we don't do that during creation, so we shouldn't be using a POST. Override the create/save if you need this for your server, instead of hacking the isNew property, which may come back to bite you.
Put
9.6 PUT
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already
existing resource, the enclosed entity SHOULD be considered as a
modified version of the one residing on the origin server. If the
Request-URI does not point to an existing resource, and that URI is
capable of being defined as a new resource by the requesting user
agent, the origin server can create the resource with that URI. If a
new resource is created, the origin server MUST inform the user agent
via the 201 (Created) response. If an existing resource is modified,
either the 200 (OK) or 204 (No Content) response codes SHOULD be sent
to indicate successful completion of the request. If the resource
could not be created or modified with the Request-URI, an appropriate
error response SHOULD be given that reflects the nature of the
problem. The recipient of the entity MUST NOT ignore any Content-*
(e.g. Content-Range) headers that it does not understand or implement
and MUST return a 501 (Not Implemented) response in such cases.
If the request passes through a cache and the Request-URI identifies
one or more currently cached entities, those entries SHOULD be
treated as stale. Responses to this method are not cacheable.
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,
Custom Adapter
App.ApplicationAdapter = DS.RESTAdapter.extend({
createRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record, { includeId: true });
//return this.ajax(this.buildURL(type.typeKey), "POST", { data: data });
return this.ajax(this.buildURL(type.typeKey), "PUT", { data: data });
},
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var id = get(record, 'id');
// you could do the same here, but it's even more incorrect
return this.ajax(this.buildURL(type.typeKey, id), "PUT", { data: data });
},
});
http://www.ietf.org/rfc/rfc2616.txt
Thank you for all of your help guys, however I have found the issue and it is ridiculously silly.
The API I have been using had a new flag "is_new" and that had been added to the model and was overwriting the "isNew" property.
Causing Ember (and me) to get very confused.
I've tweaked the API and all is good in the world!
If the model was created with createRecord, and thus has isNew == true and you call save() the expected behavior is POST. Once the record has been persisted, and it is changed, and thus isDirty == true but isNew == false then the save() will be a PUT.
This is described in the Models Guide.
I have created a Spring MVC web app.
The app makes a few calls to the controller. These calls are close/open/end game.
I make these calls using Ajax, so I can handle a response on the top of the page.
ajaxPost = function (url, action, id, onSuccess, onError) {
$.ajax({
type: "POST",
url: url + "?" + action + "=" + id,
success: function(response) {
if(onSuccess !== null) {
onSuccess(response);
}
},
error: function(e) {
if(onError !== null) {
onError(e);
}
}
});
};
The question I have is that I'm using 'POST' for the Ajax request, is that correct, or should it be 'PUT'?
My controller has a default URL, and I'm using the param attribute to decide which method to call, as I have many buttons on the page.
#RequestMapping(params = "open", method = RequestMethod.POST)
#RequestMapping(params = "close", method = RequestMethod.POST)
It doesn't sit well with me that I'm using 'POST' for these calls. Maybe it should be 'PUT'...
Any suggestions? Does it matter?
It depends on what your request should do. So there's no general rule that you should use one over the other, they have different use cases.
POST for creating a record.
PUT for updating an existing record (or putting a record at a specified location/id).
See this wikipedia article for the definitions.
One thing to note is that PUT should be idempotent, doing the same PUT request multiple times should ideally produce the same result as doing a single PUT request. However, POST is not idempotent, so doing several POST requests should (or will) create multiple new records.
So after having read this you should check what your method does, and select the corresponding request method.
Both PUT and POST may create a new record; PUT may also update/change an existing record.
The difference between POST and PUT is that PUT is expected to address the record with it's ID, so that the server knows what ID to use when creating (or updating) the record, while POST expects the server to generate an ID for the record and return it to the client after the record has been created.
Thus, a POST is addressed to the resource as a collection: POST /resource, while PUT is addressed to a single item in the collection: PUT /resource/1
Use POST. Always use POST, unless you're absolutely rock-solid certain that PUT is properly supported by your hosting system.
I posted this earlier on wordpress.stackexchange.com. However, never got a reply. Hence, trying my luck here.
I am hereby providing a detailed description of what I need and what I have done for this issue of mine. I am open to any workable solution around what I have done or maybe new suggestions.
I need to make use of user data that is retrieved using the following:
$user_data = get_user_by('login', get_query_var('user_login'));
The above code uses the username passed as a query_var in the URL. All works until here.
I make use of the above code in several Ajax callbacks (handled by admin-ajax.php) on single page load. Since, the site is targeted as a high volume site. All these Ajax requests lead to several database query for the same data. So the obvious idea to save some database queries is to pass the data to a global variable like below:
$_GLOBALS['user_data'] = get_user_by('login', get_query_var('user_login'));
And then use the same in the Ajax callbacks. Here's problem. None of the Ajax callback functions see the global $user_data variable. Before you ask, yes I have declared the global inside callback as well.
So, the obvious answer would be: why not use wp_localize_script and pass the $user_data to the Ajax callback via javascript like bellow:
In PHP:
wp_localize_script('jquery', 'ajaxVars', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'user_data' => $user_data));
In Javascript:
jQuery.ajax({
url: ajaxVars.ajaxurl,
type:'POST',
async: false,
cache: false,
timeout: 10000,
data: 'action=ajax_callback&user_data=' + ajaxVars.user_data,
success: function(value) {
alert(value);
},
error: function() {
alert(error);
}
});
However, this poses two questions:
Can an object that get_user_by('login', get_query_var('user_login')); returns be handled by wp_localize_script()?
If the answer to above question is yes, then would it not pose a security threat since the object would contain sensitive user information?
To overcome the global variable being not available to Ajax callbacks, I declared it directly in functions.php (without wrapping it inside a function). However, get_query_var('user_login') does not return any data when used directly inside functions.php making this futile exercise (You have to add it inside a function and call it via an action).
So, the question remains: how do I stop making $user_data = get_user_by('login', get_query_var('user_login')); calls for every Ajax request? Or is there a way I could get get_query_var('user_login') to work inside functions.php directly (without wrapping it inside a function) or a workaround?
Or maybe some completely new out of the box thinking?
All these Ajax requests lead to several database query for the same
data. So the obvious idea to save some database queries is to pass the
data to a global variable like below:
$_GLOBALS['user_data'] = get_user_by('login', get_query_var('user_login'));
And then use the same in the Ajax callbacks.
Each request that your application receives, AJAX or otherwise, lives completely in isolation: the code handling the requests does not share any state between them (besides whatever is persisted to a database). A global (or constant, or property, or variable, or anything) you define in one request will never be available to subsequent requests unless you store it somewhere.
There are a number of approaches to reducing the number of queries these requests are creating. One would be to retrieve the required user data on page load and pass it to subsequent requests. E.g.:
var user = 'someUser';
$.get('user-data.php?user=' + user, function(user_data) {
$.ajax('some-endpoint.php', {
type: 'POST',
data: { user: user_data },
success: function() { /* ... */ }
});
$.ajax('some-other-endpoint.php', {
type: 'POST',
data: { user: user_data },
success: function() { /* ... */ }
});
});
Alternatively, if it's the currently logged in user you're working with you can write their details to a JavaScript object on initial page load for use later.
var userData = <?php get_currentuserinfo(); echo json_encode($current_user); ?>;
Another option would be to ensure that the get_user_by results were being cached, either by Wordpress, MySQL or some other caching layer. That way it doesn't particularly matter how many times your code calls the method.
In general if lots of your endpoints are sharing functionality, you could probably stand to refactor some of that code.