PATCH Call with $batch changeset - odata

How does the SAP NetWeaver GateWay know which row in a table to update using PATCH?
Let's say I have a form, and update the 'description' for an item, how would SAP know to update the description for the item the form is for?
The form has the KEY but this is not passed back to the PATCH call because it's not been changed...

The PATCH-method works by calling the GET_ENTITY-method for your entity, merging existing data with the data you want to patch, and then running the UPDATE-method that is provided with the merged data.
You can see the implementation of this in the following method:
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~PATCH_ENTITY

Related

avoid GET_ENTITY call on bindElement for data already loaded in get_entityset

I have a Master Detail Detail-Detail Application:
Master: List of Users
Detail: Table with Qualifications of the user
Detail-Detail: Form to Edit the Qualifications
In the Detail View I have all the informations I need for the Form in the Detail-Detail view.
when I get the path of the selected listItem in the Detail View and then do a bindElement in my DetailDetail View a new Request for GET_ENTITY is called in my backend. How can I avoid this call as I already have all the data I need in my Detail View?
I could work around this issue by using a local JSON Model for the data I want to edit, but as I would like to use .hasPendingChanges in my Edit View I guess I need to bind to the original oDataModel, but as mentioned would like to avoid the GET_ENTITY backend call.
When you are binding an OData context if you call an entity the you will end in a request. i.e:
Think in a /Order('123') context then you need to bind another entity like /Order('123')/Location this is going to trigger a network request but in the case of any data like ID /Order('123')/ID this dont do any network request because properties do not trigger requests.
OData Model
Requests to the back end are triggered by list bindings
(ODataListBinding), context bindings (ODataContextBinding), and CRUD
functions provided by the ODataModel. Property bindings
(ODataPropertyBindings) do not trigger requests.
As you said you can workaround it using a JSONModel but then you will need to maintain two models, create validations, etc.
Hope this clarification helps.

How do I get the expand properties when using JIRA ''Get IDs of updated worklogs'' REST api?

Using JIRA, I get a list of IDs for worklogs updated by using this api.
/rest/api/2/worklog/updated
I can get the regular request to work, but there is a parameter called expand to display additional properties of the worklog and I can not get these properties to appear.
Things I have tried so far.
/rest/api/2/worklog/updated?expand=spentTime
/rest/api/2/worklog/updated?expand=authorName,comment
The example response in JIRA document (link mentioned above) has a field called properties. It may be used to contain expand properties.
But I don't know why my response doesn't have that field.
If what you're looking for is timeSpent, expanding properties is not the correct approach. You're going to get the relevant workLogIds returned by Get IDs of updated worklogs, then make a second REST call to Get worklogs. This call will give you timeSpent, and updateAuthor among others. However, it will not give you comments; you'll be needing a different call for that.

How to set an entity as a Navigation Property (Get) and also be able to pass a complex object into it (Patch, Put)

I'm using Entity Framework 6 and OData. I have a model A with several nav properties to other models, for example, model B. For a Get, I want to be able to call A, and Expand to B (I can do this successfully). The tricky bit is that now I want to be able to call Patch, and inside the body, include all the data for A as well as the nested data for B.
I know that EF does not accept data in virtuals, so I figured I could pull that data our in my application and null out those fields manually before saving with EF. That would be great.
However, the only way I can get OData to accept my subobject is by specifying that the type of the property B is a complex object, by adding this line to the model builder...
builder.ComplexType<B>();
I can then pass in nested data of this type on Patch, but now my Get doesn't work, because it says you can't expand to complex types, only navigational types.
So, it only works one way or the other. Any ideas on how I can accomplish something like this for both situations at the same time?
Thanks!
You can use the $ref to set up the link between entities.
For example:
POST ~/As to create a new A to As, from the response, you can get the location Id. So, you can get the key of new A
POST ~/Bs to create a new B to Bs, from the response, you can get the location Id. So, you can get the id (uri) of new B.
Then, you can use the $ref to create a link between the new A and the new B.
For the $ref, you can refer to the sample code here.

ASP.NET Model Id in ViewModel - is it safe?

Scenario:
(with an ASP.NET web app - Core or MVC)
I have a database with Users and Items for each user.
That means the UserId is a foreign key in the Items table.
From the browser I login as a User. I get my Items as a list of ItemViewModels, which are mapped (AutoMapper) to ItemViewModels via a simple api GET request.
I want to update one of the items (which should belong to me - the logged in user) via a simple API call. So I send the modified item back to the server via a PUT request as an ItemViewModel.
First approach:
The simplest approach would be to include the Item's database ID, ItemId, in the ItemViewModel - so when I receive the item to be updated as an ItemViewModel, I can map it back to the existing item in the database.
This however sounds pretty unsafe to me, as anyone could modify the PUT request with any ItemId and affect items which don't belong to the user who executed the request. Is there anything I'm missing about this approach?
Second approach:
Don't pass the database PK ItemId in the ItemViewModel.
Instead use an additional form of identification: let's say that user X has 10 items. And they are numbered from 1 to 10 using a property named UserItemId(which also exists in the database).
I can then pass this UserItemId in the ItemViewModel and when I get it back I can map it to an existing Item in the database (if all was ok with the request) or discard it and reject the request if the UserItemId didn't match anything from the logged in user's items.
Is anyone using this approach?
Pros:
The user only has access to it's own items and can't affect anyone else's since it doesn't know the actual Item ID (primary key), and any modifications are restricted to it's items.
Cons:
A great deal of extra management must be implemented on the server side for this approach to work.
Any other approaches ?
Please consider that the case mentioned above applies to all entities in the database which a client side implementation can CRUD, so it's not just the simple case described above.
The proposed solution should work for the entire app data.
I know this question has been asked here and here but the first one doesn't have a satisfying answer and I don't think the second one really applies to my situation, since it just deals with the UserId.
Thanks.
EDIT
Please consider the Item above as an aggregate root which contains multiple complex subItems each with a table in the db. And the question applies for them as much as for the main Item. That means that each subItem is passed as a ViewModel to the client.
I should mention that regarding further securing the update request:
For the first approach I can easily check if the user is allowed to change the item. But I should do this for all subItems too.
For the second approach I can check if the user can update the Item as follows: I get the userItemId of the incoming ViewModel -> I get all the logged in user's items from the database and try to find a match with the same userItemId, if I get a hit then I proceed with the update.
I think your application is not secure, if you only hide the Id.
You must check, before changing the database entity, if the user is allowed to change the entity.
In your case you should check, if your Id from the authenticated user is the UserId in your item.
If your ViewModel ist similar or identical for your API you could use a FilterAttribute in your controller.

How to send data generated from one http post to a second http post in ASP.NET MVC?

I have a view that is being used to create an invoice. The process should be as follows:
1. The user specifies a customer from a drop down and then a start date and end date.
2. They then click on a submit button, which is linked to the controller. This then builds an IList of all the jobs that meet the above criteria.
3. The page refreshes and displays the list of jobs.
4. On the same page, there is a second form which asks for an "Invoice Date" with another submit button. Clicking this should then Update an Invoice table in my DB whilst also looping through the IList of jobs and attaching invoice ID's to them (which are stored in another table in my DB).
The issue I'm having is that I've built a method which accepts the invoice data and the IList of jobs, but when I try to pass over the IList on the second submit controller method, it's null.
In the above scenario, what's the best way to get the IList built in the first post to be used in the second post?
The only way I can think of is using some sort of temporary table to store the list of jobs after the first post and then read from this in the second when updating the invoice table. Is this an acceptable method to achieve what I want? Or is there a better way that my lack of experience is missing? xD
What bugs me about that method above is that if the user leaves the page before posting the second time, the temporary table will then have a list of rogue jobs which could be called up unexpectedly the next time.
Hope I've explained this well enough. Thanks in advance.
The temporary table that you can use (which is built in MVC) is the TempData dictionary. It's persisted inside the Session, and the values get deleted when you use them.
BTW, have you thought of using Ajax instead of posting and refershing? This means that you always have the data with you, as you're on the same page. You don't have to carry state around.
UPDATE:
Errr wait, when you say that the list is NULL are you talking about a List recieved in your Action as a parameter? If you are, this article shows how to databind a collection.
UPDATE 2:
I have had second thoughts about using this method (getting data from the client), as it could lead to some security issues.
If you don't want to query the DB again, TempData/Session is a possible solution.
Since the list of jobs is not modified by the user on the second page, why don't you just grab it again in the controller action that handles your second submit?

Resources