OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
855 stars 473 forks source link

Use EntitySetConfiguration to setup MediaEntity #1923

Open norcino opened 5 years ago

norcino commented 5 years ago

Goal As described here: http://docs.oasis-open.org/odata/odata-json-format/v4.0/cs01/odata-json-format-v4.0-cs01.html#_Toc365464710 I would like my entity to return mediaReadLink and mediaContentType when getting by ID an entity.

Expectation Given a valid setup code as the following:

var builder = new ODataConventionModelBuilder(serviceProvider);
var entitySetConfiguration = builder.EntitySet<Entity>(nameof(Entity) + "s");

entitySetConfiguration.HasEditLink(c => new Uri("any"), true);
entitySetConfiguration.HasReadLink(c => new Uri("any"), true);

entitySetConfiguration.EntityType
                .MediaType() // This adds HasStream true in the metadata
                .Filter(QueryOptionSetting.Allowed, nameof(Entity.Id))
                .Filter(QueryOptionSetting.Disabled, nameof(Entity.Description));

I would like to be able to add something like the below:

entitySetConfiguration.HasMediaReadLink(c => new Uri($"{c.GenerateSelfLink(false).AbsolutePath}/$value"), true);
entitySetConfiguration.HasMediaContentTypeReadLink("application/xml");

or alternatively:

.MediaType(c => new Uri($"{c.GenerateSelfLink(false).AbsolutePath}/$value", "application/xml");

For a request GET http://server/odata/Entity/1 I expect the response payload to look like

{
    "@odata.context": "http://server/odata/$metadata#Entity/$entity",
    "@odata.mediaReadLink": "Entity(1)/$value",
    "@odata.mediaContentType": "application/xml",
    "Id": 1,
    "Description": "Example"
}

Current solution Currently the only way I found to do it can be found here https://github.com/kevin-osborne/ODataSample, where OData is customised to use tailored Serializer and SerializerProvider. I personally don't like this solution which requires a lot of effort to put in place for such simple requirement which should come out of the box to be compliant with odata 4.1.

Affected assemblies I use net core Microsoft.AspNetCore.App 2.2.0 and Microsoft.AspNetCore.OData 7.2.1

UPDATE: More info I found GetStreamReadLink method in ODataResourceMetadataBuilder and ODataConventionalResourceMetadataBuilder. Those are for properties (I didn't try with a property stream I don't know how to set it up), is there anything like that for a whole entity? Note that my knowledge of OData is not huge and I might be very well mistaking or misunderstanding something.

The method BuildStreamReadLinkUri in ODataConventionalUriBuilder, seems to be designed to work with properties or when it is null, as a Uri generator for the default media resource, which I believe is the entity itself?

In the "old" OData for .net framework I was use to use code like this to do the job:

var model = modelBuilder.GetEdmModel();
var entityTypeName = typeof(Entity).FullName;
var entityType = (IEdmEntityType) model.FindDeclaredType(entityTypeName);
model.SetHasDefaultStream(entityType, true);
NetTecture commented 5 years ago

You are not alonw. The whole streaming thing is a mess right now, not helped by the documentation at https://docs.microsoft.com/en-us/odata/ not having a single line mentioning streaming and media url's anymore.