What are the best REST endpoint for the same resource with two operations? - api-design

I have one resource /foo that has some variations.
On the "foo" page I can save an "foo" and submit an "foo". If I save, I can change/update it and submit, if I submit, I can't update anymore.
What are the endpoints that I can use for this?
I'm thinking about:
POST /foo Save an "foo";
PUT /foo/:id Update an "foo";
But what can I do to submit an "foo" that have been saved previously and what I can do if it is submitted without a previous save?

Related

Meteor: Best way to create a new document in a collection before visiting a route?

Every time a user visits a specific route, I'd like for a new document to get created that will act as a "draft" that the user will edit until they decide to publish it.
Another way to think about this is that I want to redirect a user to a new page displaying the document after a successful insert of the document.
When I phrase it like that, I think I've basically answered my own question. In this case I would just call a Meteor method that creates and inserts the new document, then in the callback method I would use iron-router's Router.go method to redirect to the url using the new _id as a parameter. Is there a better way?
It's a bad idea to get collection created automatically upon visiting a route. What happen if user visit the route unintentionally?
Nevertheless, you can achieve it by inserting a document on publish function and it will get created upon Meteor.subscribe.
Meteor.publish('test-draft', function(options){
var _id = Test.insert({a: 'b'});
return Test.find({_id: _id})
})
If I understand what you're doing correctly, I think the easiest thing would be to just create an object and put it in a Session variable and not mess with creating a document in a collection until you're done editing it.
You can create the object and stick it into Session in Templates.myTemplate.rendered = function() { ... }. And then when it's been satisfactorily edited and submitted pass the Session variable to a Method that inserts it as a new document.

In which Symfony event can I have access to which submit button was clicked?

I would like to do some transformation on the submitted data based on which button on my form was clicked. Here is the scenario:
I have a text field named chain which holds the command chain.
I have a command text field that holds the last command.
I have two buttons on the form: Send and Send chain.
When Send is clicked, chain is set to command, erasing whatever was in it before. When Send chain is clicked, however, the contents of command are added to the end of chain after a delimiter, effectively creating a chain of commands.
I need to be able to check to see which of these two buttons was clicked so that I can set chain to the appropriate value.
Why am I not doing this in the controller? The problem is that I need to modify the value of chain. Since I cannot modify the values of an already-submitted form, I need to do this in an event, I assume. As I mentioned above, I need chain to either be equal to command, or chain + [delimiter] + command.
If I understood you correctly, you don't need an event at all. There is a built in method isClicked() since #2.3. Example from documentation:
if ($form->isValid()) {
// ... do something
// the save_and_add button was clicked
if ($form->get('save_and_add')->isClicked()) {
// probably redirect to the add page again
}
// redirect to the show page for the just submitted item
}
Link to chapter.
Update
Normally, the code I showed can be used in event - FormEvents::POST_SUBMIT to be precise, but as you already pointed out, you can not modify form data after submission. To be honest I can't come up with perfectly working example, so I will share an idea hoping it will lead to something, or at least until someone else suggest something else.
How about you add a hidden non mapped field to your form. Then (assuming you are allowed to use javascript in your form) you can attach event listener on when form is submitted and based on which button was clicked you can populate that hidden field with specific value. After that you can add event listener to your FormType and read the value of this hidden field, using FormEvents::POST_SET_DATA.
I am sorry I can not be more helpful as of now. If I came up with something I will edit my post.
Here is what I needed to do:
I couldn't use the POST_submit event because I couldn't transform the data after submission.
The isClicked() of both buttons returned false in other events, because the form hadn't been submitted yet.
The solution is something like this:
$data = $event->getData();
if (isset($data['send']) {
// transform the values here
}
In other words, the only way to check if a particular button was clicked is to check to see if its name exists as an index in the array returned by $event->getData().

How to get url data of form using post method

In wordpress, I'm using a template, which is used to store url data from sender page in database. This task is completed well when I use GET method for submitting the form, but when I use POST, then the whole $_POST array is empty in my template. What is the reason for that and how can I solve it?

Saving QueryString to protect URL manipulation

Is there a way to save the querystring ids after the page load? the reason why i am looking is that ...i should be back and forth with pages and more importantly if the user try to manupluate the ids then it should not effect the result of my page since i will be reading the Ids not from querystring but from some save prop or something like that.
for an example: let says the page loads very first time... i have this url:
http://www.somesite.com/Shop/Product/Detail.aspx?ProductId=100
and if the user try to modify the querystirng and re-load the page then the page_load should not read from querystring rather from saved prop or something???
In your page load event look at the Page.IsPostBack property. It is false when a page is first loaded. You should validate your parameters then and perhaps save them to session or viewstate.
If Page.IsPostback = false Then
'Validate Request("ProductID") here
'Save in viewstate or session state
Else
'Retrieve ProductID from viewstate or session state
End If
If a user changes the query string, you should consider it a new page load.
This would not work since it's against the very basic nature of Internet. Internet is stateless.
Everytime user changes the querystring, it will be treated as a new Url, storing the parameters will be of no use. Page.IsPostback won't work either since every Url change will be a first hit.
Saying that, you can still work around it,
With every Url, you can pass a unique identifier (like a GUID.)
As soon as page hits, you can save parameters in session and work with them and use the Guid to map the two requests.
But the problem remains here, if the user changes that Guid then again it will be treated as a new request. You can go one step ahead and start saving that GUID to make sure that only system generated GUIDs are handled but overall it will just make your system complex.
My guess is that you might be looking at a wrong solution for your problem. If you can share your actual aim then we might be able to recommend you something more tangible.
You can not stop users from editing querystring values and trying to see content of another page or execute something. what you can do is you can check in the page load that this user has sufficient permission to access this page.
Ex : www.mysite.com/editproduct.aspx?productid=4
In editproduct.aspx, you have to check whether the product 4 has access by the current user who is accessing the page.( May he should be the creator/ he should be in a specific power users group etc... depending upon your scenario). If he has access, show the edit form to the user, else hide it and show a message saying "you are not authorized to access this resource."
There is no way; however, you can use session to validate when the Page_load is called.
If ( Page.isPostBack = true ) {
Session("SAVE") = false;
}
For a while in the before the Request.Querystring statement, you validate the 'save' session state.

When no record associated with the given id, which action should the action method do? Returning NoFound view or redirecting to NoFound action method?

In Details, Edit, Delete action methods we have id parameter to retrieve the corresponding record from the database.
If no record corresponds to the id, we have 2 choices:
The executing action method returns a
specific view, which is usually named as
NoFound.cshtml under Views\Shared
directory, to inform the user that the
id is not valid.
or
The executing action method redirect
the user to a specific action method,
for example public ActionResult
NoFound (string message), to inform
the user about the issue.
My question is:
When no record associated with the given id, which action should the action method do? Returning NoFound view or redirecting to NoFound action method?
Edit 1
I need reasons from technical point of view such as security and performance.
It's all personal preference. In my opinion though, the real thing that should happen in this situation is a 404 response code should be sent back to the client. You can have custom 404 pages that give you the best of both worlds.
Refer to Step 5 on this answer - custom 404, proper 404 response code, proper handling of the "item not found" case.
I would return a "Not found" view, because this way an URL with ID could be stored in favorites and will became valid when record with this ID will be available.
I would recommend still returning a 404 error. The order of the parameters in the route is irrelevant, some people prefer {controller}/{action}/{id}, in some cases {controller}/{id}/{action} might make more sense. In either case if all three parameters are required for it to be considered a valid request and one is missing you should return a 404. It will also make testing your site much easier as if you return a view it will have a result code of 200 and make it much more difficult to track down broken links. 404 errors are universally recognized as a problem when doing site analysis.

Resources