Simple Select-Dropdown for a NavigationProperty - odata

For a current project, we're using Olingo in backend for OData v4 data access and openui5 as frontend framework. We know, that odata v4 is in a more experimental state in openui5 but we're doing not so bad with it. As it is normal for us, to use a workaround here and there, we're struggeling with following problem right now where I think there should be a really simple way instead of building a workaround.
Simplified oData v4 Model:
<EntityType Name="Notification">
<Key>
<PropertyRef Name="uid"/>
</Key>
<Property Name="uid" Type="Edm.Int32"/>
<Property Name="recievedAt" Type="Edm.Date"/>
<NavigationProperty Name="NotificationType" Type="rest.odata.BaseData" Nullable="false"/>
</EntityType>
<EntityType Name="BaseData">
<Key>
<PropertyRef Name="key"/>
</Key>
<Property Name="key" Type="Edm.String"/>
<Property Name="title" Type="Edm.String"/>
</EntityType>
The BaseData-Entity is used for different key-value-lists - in this case for a NotificationType. We have couple of types summarized and represented in an EntitySet:
<EntitySet Name="basedataNOTIFICATIONTYPES" EntityType="rest.odata.BaseData"/>
Now we're struggeling in the frontend with a simple sap.m.Select-Dropdown which should define the NotificationType of our Notification.
The Select-Control is defined like this:
var oControl = new sap.m.Select(sName, {selectedKey: "{NotificationType/key}"});
oControl.bindItems({
path: "/basedataNOTIFICATIONTYPES"
})
(I simplified the code very much)
The parent form is binded to a specific /Notification context.
This is what happens: The Select-Dropdown shows the current saved NotificationType of our specific /Notification. If I select another NotificationType from the dropdown, ui5 sends a PATCH Request to the EntitySet /basedataNOTIFICATIONTYPES. This is not the behaviour I expected. I need a PATCH Request sent to the specific /Notification(XXX)/NotificationType/key to update it.
Has anyone a hint for me?
Thanks in advance! :-)

Related

ASP.NET Core 5 OData: requesting an individual property not found

I am creating an OData service on .NET 5 using Microsoft.AspNetCore.OData.
In my EDM model there is a collection of reports that is based on the following entity type:
<EntityType Name="Report">
<Key>
<PropertyRef Name="ReportId" />
</Key>
<Property Name="ReportId" Type="Edm.String" Nullable="false" />
<Property Name="ReportName" Type="Edm.String" />
<NavigationProperty Name="Units" Type="Collection(DataModelBase.UnitInfo)" />
<NavigationProperty Name="Data" Type="Collection(DataModel.EntityInfo)" />
</EntityType>
When I send the request serviceRoot/Reports('1'), I can see the report with ReportId='1' showing up correctly.
However, if I try serviceRoot/Reports('1')/ReportId, which should work according to the OData Basic Tutorial, I get a 404 not found error.
My app configuration is as follows (F#):
app.UseRouting()
.UseEndpoints(fun endpointBuilder ->
endpointBuilder.MapControllers() |> ignore;
endpointBuilder.Select().Expand().Filter().Count().OrderBy() |> ignore;
endpointBuilder.MapODataRoute("odata","odata",edmModel) |> ignore
)|> ignore
And services:
services.AddControllers(fun mvcOptions -> mvcOptions.EnableEndpointRouting <- true) |> ignore;
services.AddOData() |> ignore
Can anyone please tell me what I am missing?
After some investigation, I think I have the answer to my question: the parameter routes are not generated automatically like I expected them to be. You need to implement the controllers for the routes yourself.

What is the correct response for a GET request to anempty OData Navigation property

Say, for such an entity defined below, what is the correct response for GET "serviceRoot/entity(1)/nav"? Assuming entity with id 1 has valid values, but its stored key for the 'nav' reference is null.
<EntityType Name="entityType">
<Key>
<PropertyRef Name="id"/>
</Key>
<Property Name="id" Nullable="false" Type="Edm.Integer"/>
<Property Name="name" Nullable="false" Type="Edm.String"/>
<NavigationProperty Name="nav" Nullable="true" Type="this.navType"/>
</EntityType>
<EntityType Name="navType">
<Key>
<PropertyRef Name="navId"/>
</Key>
<Property Name="navId" Nullable="false" Type="Edm.Integer"/>
<Property Name="name" Nullable="false" Type="Edm.String"/>
</EntityType>
<EntityContainer Name="Container">
<EntitySet EntityType="navType" Name="navSet"/>
<EntitySet EntityType="entityType" Name="entity">
<NavigationPropertyBinding Path="nav" Target="this.navSet"/>
</EntitySet>
</EntityContainer>
204 No Content is the correct response according to the OData v4 specification.
If the relationship terminates on a single entity, the response MUST be the format-specific representation of the related single entity. If no entity is related, the service returns 204 No Content.
Source: Requesting Related Entities
Good guess!

How to select and expand on properties which are available only in derivedtypes

I have three entities, in an inheritance hierarchy as shown below.
<EntityType Name="Base" Abstract="true">
<Property Name="id" Type="Edm.String" Nullable="false" />
</EntityType>
<EntityType Name="Derived1" Abstract="true" BaseType="Base">
<NavigationProperty Name="idps" Type="Collection(Idps)" />
</EntityType>
<EntityType Name="Derived2" Abstract="true" BaseType="Base">
<NavigationProperty Name="attributes" Type="Collection(Attributes)" />
</EntityType>
I want to support $select and $expand query options for idps and attributes.
/base?$select=idps gives me below error
The query specified in the URI is not valid. Could not find a property named 'idps' on type 'Base'."
What would be the right odata option and how can I support that?
ODL supports type cast segment in the $select and $expand.
Here's some test cases that you can refer to:
1) https://github.com/OData/WebApi/blob/master/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/NavigationPropertyOnComplexType/SelectImprovementOnComplexTypeTests.cs#L141
2) https://github.com/OData/WebApi/blob/master/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/NavigationPropertyOnComplexType/SelectImprovementOnComplexTypeTests.cs#L284
The test cases cover the complex type type cast, so does it for entity type cast.
I was able to resolve this issue with a query similar to the following:
/base?$select=Derived1/idps
In my case, my OData entity types have an explicit namespace on them, so I had to actually use a query similar to the following:
/base?$select=Namespace.Derived1/idps

How to change the metadata EntityContainer from "Default" in JayStack odata-v4-server

I'd like to set my own EntityContainer name other than the default 'Default' viewable in the XML $metadata schema.
I'm aware we can define our own Schema's using the odata-v4-metadata package, but this would mean the metadata would be returned as a JSON file instead of XML. I'm using a proxy generation script on the metadata file which depends on it being returned as XML.
You can see the tags which hold the "Products" EntitySets is called "Default". I'd like to change this if possible, without resorting to using a JSON schema.
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Northwind">
<EntityType Name="Product">
<Key>
<PropertyRef Name="_id"/>
</Key>
<Property Name="_id" Type="Edm.String" Nullable="false">
<Annotation Term="Org.OData.Core.V1.Computed" Bool="true"/>
</Property>
</EntityType>
<EntityContainer Name="Default">
<EntitySet Name="Products" EntityType="Northwind.Product"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Place the following annotation:
#odata.container("MyContainerName")
Above all classes you want to contain under the container "MyContainerName"

how are actions defined in OData V3 metadata?

Hi i'm create a code generation tool for Odata, so far the odata v4 have been really simple to implement.
Regarding odata V3 i have been having troubles with the metadata because I don't know where actions are defined so far I have been only able to see FunctionImport on metadata but not actions, are FunctionImport an equivalent to actions for OData V3? if not can you point on which node of the metadata are the actions located ?
thanks
Actions can be bound or unbound and can be added to the metadata(EDM) as follows:
builder.Entity<entityname>.Action("actionname").Parameter<type>("paramtername").Returns<type>();
Here, builder can be either ODataBuilder or ConventionalOdataBuilder.
If you want the action to be unbound, you can remove the Entity and directly add it to the builder.
If you wish to add the action to IEdmModel directly, you can add the action as a schemaelement.
Source:https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/odata-actions
Edit: Actions are defined in metadata as follows:
<Schema Namespace="Default" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="Movies" EntityType="ODataActionsSample.Models.Movie" />
<FunctionImport Name="SetDueDate" ReturnType="ODataActionsSample.Models.Movie" IsBindable="true" EntitySet="Movies" m:IsAlwaysBindable="true">
<Parameter Name="bindingParameter" Type="ODataActionsSample.Models.Movie" />
<Parameter Name="DueDate" Type="Edm.DateTime" Nullable="false" />
</FunctionImport>
<FunctionImport Name="CreateMovie" ReturnType="ODataActionsSample.Models.Movie" EntitySet="Movies">
<Parameter Name="Title" Type="Edm.String" FixedLength="false" Unicode="false" />
</FunctionImport>
</EntityContainer>

Resources