Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to create such an endpoint api/Student('dany')/Girlfriends using angular-odata? #44

Closed
icapri opened this issue Sep 7, 2021 · 10 comments

Comments

@icapri
Copy link

icapri commented Sep 7, 2021

Holà Diego!

In C# it is possible to write something like this:

var tripEvent = client
    .For<Person>()
    .Key("russellwhyte")
    .NavigateTo<Trip>()
    .Key(1003)
    .NavigateTo(x => x.PlanItems)
    .As<Event>()
    .Set(CreateEventDetails())
    .InsertEntryAsync();

I would like to know whether I have the posibility to create a new Girlfriend DTO for the Student called "dany".

Which means I want to send a POST request to .../api/Student('dany')/Girlfriends by using your package client-side.

Thank you very much in advance for your response!

Kind Regards,

Kapri

@diegomvh
Copy link
Owner

diegomvh commented Sep 7, 2021

Hola @i-kapri

Assuming that the code in #C creates a new EventDetails and adds it to the collection of PlanItems

// Resource for alice
var alice = client.entitySet<Student>("Student").entity("alice");
// Resource for bob
var bob = client.entitySet<Student>("Student").entity("bob");
// Navigate to Girlfriends of bob and add alice as a new one :) asume than Girlfriends is a collection
bob.navigationProperty<Student>("Girlfriends")
  .reference()
  .add(alice)
  .toPromise();

There is an issue regarding relationships here #21

Hope this helps

Diego

@icapri
Copy link
Author

icapri commented Sep 8, 2021

Holà @diegomvh !

Gracias por su respuesta!

In my situation, it looks a bit different:

var alice = { Name : 'Alice' };
// Resource for bob
var bob = client.entitySet<Student>("Student").entity("bob");
// Navigate to Girlfriends of bob and add alice as a new one :) asume than Girlfriends is a collection
bob.navigationProperty<Student>("Girlfriends")
  .reference()
  .add(alice)
  .toPromise();

Is this possible with angular-odata ? In C# I can write the same/similar code with OData-Client:

this.ODataClient.For<Student>("Student")
               .Key("bob")
               .NavigateTo(s => s.Girlfriends)
               .Set(new Dictionary<string, object> {{ "Name", "Alice" }})
               .InsertEntryAsync()
               .Wait();

Gracias de antemano por su ayuda!

Muchos Saludos
Kapri

@diegomvh
Copy link
Owner

diegomvh commented Sep 8, 2021

Hi @i-kapri

Is it possible to modify an entity or a collection through a navigation property?
OData/WebApi#945 (comment)

In the ODataClient examples the insertions are made on the entity sets
https://github.com/simple-odata-client/Simple.OData.Client/wiki/Adding-entries

... After the entities are created they are eventually linked to each other (this is OData 3)
https://github.com/simple-odata-client/Simple.OData.Client/wiki/Linking-and-unlinking-entries

Something equivalent to creating and adding to the collection using angular-odata is:

// Student EntitySet Resource
var students = client.entitySet<Student>("Student");
// Create Entity
 //if the prefer return=representation header is set the return of the post is de representation of alice in the backend
// https://github.com/diegomvh/angular-odata/blob/664a28306782588f26e059eaf6cc258963811c0f/projects/angular-odata/src/lib/types.ts#L34
var alice = await students.post({ Name : 'Alice' }).toPromise();
// Resource for bob
var bob = students.entity("bob");
// Navigate to Girlfriends of bob and add alice as a new one :) asume than Girlfriends is a collection
//  the add method needs a resource that point to alice
bob.navigationProperty<Student>("Girlfriends")
  .reference()
  .add(students.entity(alice.Name))
  .toPromise();

Each type of resource inherits from a base type that guarantees the possibility of performing the actions of get, post, patch, delete, etc but does not publish them except to build its own functionality according to my interpretation of the standard :)

For example, you can create and get entities from an entity set


... but it can only be get from a navigation property

As I discover a little more of the standard I try to incorporate shortcuts to resources according to their type, today the shortcuts are based on get more than post

Thanks for write in spanish :)

Saludos
Diego

@icapri
Copy link
Author

icapri commented Sep 9, 2021

Hi Diego!

Check this out: https://www.odata.org/getting-started/advanced-tutorial/#createContain

The example in the article above shows that it is possible to create a trip for a person using the endpoint serviceRoot/People('russellwhyte')/Trips. Which means that it seems to be possible to modify an entity or a collection through a navigation property.

Below the OData Examples of importance in our case:

Create a Derived Entity
The request below creates an event entity in trips. Event derives from PlanItem.

POST serviceRoot/People("russellwhyte")/Trips(1003)/PlanItems
OData-Version: 4.0
Content-Type: application/json ; odata.metadata=minimal
Accept: application/json

{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"ConfirmationCode": "4372899DD",
"Description": "Client Meeting",
"Duration": "PT3H",
"EndsAt": "2014-06-01T23:11:17.5479185-07:00",
"OccursAt": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.EventLocation",
"Address": "100 Church Street, 8th Floor, Manhattan, 10007",
"BuildingInfo": "Regus Business Center",
"City": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.City",
"CountryRegion": "United States",
"Name": "New York City",
"Region": "New York"
}
},
"PlanItemId": 33,
"StartsAt": "2014-05-25T23:11:17.5459178-07:00"
}


Response Payload

 Response HTTP/1.1 201 Created
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips(1003)/PlanItems/$entity",
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"PlanItemId": 33,
"ConfirmationCode": "4372899DD",
"StartsAt": "2014-05-25T23:11:17.5459178-07:00",
"EndsAt": "2014-06-01T23:11:17.5479185-07:00",
"Duration": "PT3H",
"Description": "Client Meeting",
"OccursAt": {
  "Address": "100 Church Street, 8th Floor, Manhattan, 10007",
  "City": {
    "CountryRegion": "United States",
    "Name": "New York City",
    "Region": "New York"
    },
"BuildingInfo": "Regus Business Center"
  }
}
Update a Derived Entity
The request below updates an event. Event derives from PlanItem.

PATCH serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(5)/Microsoft.OData.SampleService.Models.TripPin.Event
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json

{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"Description": "This is a new description"
}


Response Payload

HTTP/1.1 204 No Content
Delete a Derived Entity
The request below deletes the flight plan item with Id '21' from a trip of person. Flight derives from PlanItem.

DELETE serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(21)/Microsoft.OData.SampleService.Models.TripPin.Flight

Response Payload

HTTP/1.1 204 No Content

Another helpful article would be this one:
https://devblogs.microsoft.com/odata/tutorial-sample-containment-is-coming-with-odata-v4/

Kind Regards
Kapri

@icapri
Copy link
Author

icapri commented Sep 9, 2021

Hello Diego!

I achieved my goal with a quick hack by accessing the protected method post() in your base class ODataResource like this:

public async create(dto: Partial<TDto>): Promise<TDto> {
      return this.post(dto).pipe(map(o => o.entity!)).toPromise();
   }

Hopefully you can extend your library!

Kind Regards
Kapri

@diegomvh
Copy link
Owner

diegomvh commented Sep 9, 2021

Hi Kapri

You're right!
Based on the examples and continuing with the idea of ​​publishing the behavior that is specific to each resource, it is a matter of incorporating the functionality in the navigation resource.
At some point I am always evaluating the possibility of using words like create, destroy, update for the methods that expose the functionality of the post, delete, put respectively ... I accept suggestions .

For now "challenge accepted"

By the way the As of ODataClient in C# is cast in angular-odata.

Regards
Diego

@icapri
Copy link
Author

icapri commented Sep 10, 2021

¡Hola de nuevo Diego!

¡Infórmeme cuando publique la nueva versión de su paquete!

¡Gracias por adelantado por tu respuesta!

Muchos Saludos
Kapri

diegomvh added a commit that referenced this issue Sep 11, 2021
@icapri
Copy link
Author

icapri commented Sep 13, 2021

¡Hola Diego!

I saw that you had committed new changes regarding this issue.

Firstly, let me thank you for your consideration of my feature suggestion.

At second, I would like to know when the next release takes place so that I can proceed with my project.

Thank you in advance!

Kind Regards
Kapri

@diegomvh
Copy link
Owner

Hi Kapri

I released the changes on version 0.75.0 today.
Many thanks again for your contribution to enhance the library. And my knowledge of the OData Standard.
Still remains me choose good names for http verbs... but for now using post, put, delete on navigation properties you can access to the new functionality.

Regards
Diego

@icapri
Copy link
Author

icapri commented Sep 13, 2021

Hi again Diego!

This is good news!

Thank you again for your quick reaction and for adding the requested feature to your project!

Kind regards
Kapri

diegomvh added a commit that referenced this issue Oct 1, 2021
Applying the improvements of the issue #44 to collections
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants