When I needed to add some functions (or actions) to my odata server for my internal database that I want to connect to Dynamics CRM, I found the documentation challenging. Even blogs on this topic did not help much. I had alot of errors.
When setting up a function in your EDM model you can following the instructions. In my domain model, I have a SystemUser and PrincipalPermissions which are a set of permissions needed to determine if you can CRUD an entity or a collection of entities. Nothing special here and I am using the same names as those found in Dynamics CRM for convenience here but just remember, this is my separate database that I need an OData front end for:
var systemUserES = builder.EntitySet<SystemUser>("SystemUsers");
var retrievePrincipalAccessFunc = builder.EntityType<SystemUser>()
.Function("RetrievePrincipalAccess")
.ReturnsFromEntitySet<PrincipalPermission>("PrincipalPermissions"); // return single instance
retrievePrincipalAccessFunc.Parameter<string>("type");
retrievePrincipalAccessFunc.Parameter<Guid>("id").Optional();
Here’s the final controller declaration:
[HttpGet]
[ODataRoute("SystemUsers({key})/Encore.RetrievePrincipalAccess(type={otype},id={oid})")]
public ActionResult<PrincipalPermission> RetrievePrincipalAccess(
Guid key,
string otype,
Guid? oid) { ... }
Note the following which I did not find documented:
- The function parameter names in the EDM spec are for the actual parameters in the function call and not the parameter names in {…} for the actual C# function.
- The names in the {…} need to match, order does not matter.
- The GUID in the function call itself (in the HTTP call) should not be quoted even though its a function argument. The type is GUID and GUIDs should not be quoted in the HTTP URL.
- The parameters in the parameter list do not have
[FromODataUri]
. If you keep those on the parameters, your route will throw an exception during startup indicating the route is invalid. If you did nothave anODataRoute
then you would want[FromODataUri]
on the parameters. The explicitODataRoute
removes the need forFromODataUri
.
I worked through this fast enough, but I do find that things like this slow me down a bit.
At least its all working!