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>
Related
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! :-)
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
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"
My OData v4 client uses generated classes based on the 6.x version of Microsoft.OData.Client.
Now it needs to call an action with the following definition:
<Action Name="Resolve">
<Parameter Name="CertRequestEntity" Type="CertificationRequest" />
<Parameter Name="CertRequestId" Type="Edm.String" Nullable="false" Unicode="false" />
<Parameter Name="RequestSuccess" Type="Edm.Boolean" Nullable="false" />
<Parameter Name="RejectedMessage" Type="Edm.String" Unicode="false" />
</Action>
It is easy to construct primitive parameters with the aid of the BodyOperationParameter class, but I cannot find any documentation on the proper way to construct an entity reference as a parameter. Is this possible? (I ended up using HttpClient with a hand-rolled JSON body.)
Note that the definition above, as written, is invalid; the type of the first parameter should be namespace qualified.
If you have control over the schema, the simplest solution would be to make this a bound action (IsBound="true" on the action definition). Bound actions are similar to extension methods in .NET -- the first (entity) parameter becomes the "binding parameter", and you would call the action by appending the action name (/Resolve) to the URL for the CertificationRequest that you wanted to resolve, passing the remaining (non-binding) parameters in the body.
In my NHibernate mapping file I've had two classes mapped where one classes property had the same name as another classes name (Group).
<class name="Machine" table="SpisMaszyn" dynamic-update="true">
<cache usage ="read-write"/>
<id name="ID" column="ID" type="int">
<generator class="native" />
</id>
<property column="NazwaMaszyny" name="MachineName" />
<property column="Grupa" name="Group" />
</class>
<class name="Group" table="SpisGrup" dynamic-update="true">
<cache usage ="read-write"/>
<id name="ID" column="ID" type="int">
<generator class="native" />
</id>
<property name="Name" column="Nazwa" />
</class>
I don't know why but if the names are the same the code wasn't working properly. In my ModelState I was getting null value for Group. I'm not sure what can be causing it.
Do you have any idea what might cause this ?
The mapping is correct. A fact that some property and some other class name share same name, is not any issue for NHibernate. Check the underlying column content. Run profiler to see the SQL Query and assure that returned data are there...
original assumpiton that many-to-one is required removed