-
Notifications
You must be signed in to change notification settings - Fork 713
OData API explorer only showing $select and $expand, help #1038
-
Hi,
Does anyone know what might cause the API explorer to only show $select
and $expand
query options sometimes?
I've enabled all query options globally and query options like $filter
do actually work, but they are simply not showing up in Swagger for some unknown reason.
I'm still targeting .NET 6.0, maybe I'm using an invalid combination of packages?
<ItemGroup> <PackageReference Include="Asp.Versioning.OData" Version="6.4.0" /> <PackageReference Include="Asp.Versioning.OData.ApiExplorer" Version="6.4.1" /> <PackageReference Include="Microsoft.AspNetCore.OData" Version="8.2.3" /> <PackageReference Include="Microsoft.OData.Core" Version="7.18.0" /> <PackageReference Include="Microsoft.OpenApi" Version="1.4.4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> </ItemGroup>
My middleware pipeline config:
var mvc = services.AddControllers(); services.AddEndpointsApiExplorer(); mvc.AddOData((odata, sp) => { // Enable all query features globally // You can restrict features per endpoint using [EnableQuery(AllowedQueryOptions = ...)] odata.EnableQueryFeatures(maxTopValue: 100); }); var versioning = services.AddApiVersioning(options => { options.DefaultApiVersion = new ApiVersion(4, 0); // Reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions" options.ReportApiVersions = true; // Allows a client to make a request without specifying an api-version // The value of options.DefaultApiVersion will be assumed options.AssumeDefaultVersionWhenUnspecified = true; }); versioning.AddOData((odata) => { odata.AddRouteComponents("odata"); }); versioning.AddODataApiExplorer(options => { // Add the versioned api explorer, which also adds IApiVersionDescriptionProvider service // Note: the specified format code will format the version as "'v'major[.minor][-status]" options.GroupNameFormat = "'v'VVV"; });
My controller:
I noticed the use of ProducesAttribute
and ProducesResponseTypeAttribute
affects the OData API explorer? Maybe not in a good way.
[ApiVersion(4.0)] public class DocumentsController : ODataController { private ILogger<DocumentsController> _logger; public DocumentsController(ILogger<DocumentsController> logger) { _logger = logger; } [EnableQuery] [Produces("application/json")] [ProducesResponseType(typeof(IQueryable<DocumentODataDTO>), Status200OK)] [ProducesResponseType(Status400BadRequest)] [ProducesResponseType(Status401Unauthorized)] [ProducesResponseType(Status403Forbidden)] public async Task<ActionResult<IQueryable<DocumentODataDTO>>> GetDocuments( [FromHeader(Name = "X-BusinessUnitCode"), Required] string businessUnit, [FromServices] IMediator mediator, [FromServices] IConfigurationProvider mapperConfiguration, CancellationToken ct) { }
If I remove the Produces
attributes then I get the desired behavior, i.e. all OData query options are available in Swagger.
I might just be using the attributes incorrectly?
Thanks for any help.
Beta Was this translation helpful? Give feedback.
All reactions
OData, both in protocol and implementation, only supports returning JSON or XML. To be fully compliant, the payloads are supersets that are specific to OData. You cannot return just any 'ol JSON. I'm not sure if XML is even still supported. I know it's not by default.
In the context of OData, there should be no need to specify [Produces]
. OData-based responses will list the equivalent values from the OData InputFormatter
and OutputFormatter
implementations. The API Explorer knows that the results are for OData because you are using ODataController
, which has [ODataRouting]
applied. You should notice that there are actually several media types reported (but you probably expected one). You'...
Replies: 1 comment 4 replies
-
OData, both in protocol and implementation, only supports returning JSON or XML. To be fully compliant, the payloads are supersets that are specific to OData. You cannot return just any 'ol JSON. I'm not sure if XML is even still supported. I know it's not by default.
In the context of OData, there should be no need to specify [Produces]
. OData-based responses will list the equivalent values from the OData InputFormatter
and OutputFormatter
implementations. The API Explorer knows that the results are for OData because you are using ODataController
, which has [ODataRouting]
applied. You should notice that there are actually several media types reported (but you probably expected one). You're free to filter down things how you like, but that is the true set of supported media types.
I have also found Swashbuckle was adding application/json
if it wasn't specified, which is usually undesired and possibly problematic. The OData with OpenAPI example shows how to deal with that:
aspnet-api-versioning/examples/AspNetCore/OData/ODataOpenApiExample/SwaggerDefaultValues.cs
Line 27 in 471eb04
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks, I removed the attributes, everything seems to work as expected now.
I don't really understand how content negotiation works in OData. I can see the media types you are talking about, but I've no clue what they are used for.
application/json;odata.metadata=minimal;odata.streaming=true
application/json;odata.metadata=minimal;odata.streaming=false
application/json;odata.metadata=minimal
application/json;odata.metadata=full;odata.streaming=true
application/json;odata.metadata=full;odata.streaming=false
application/json;odata.metadata=full
application/json;odata.metadata=none;odata.streaming=true
application/json;odata.metadata=none;odata.streaming=false
application/json;odata.metadata=none
application/json;odata.streaming=true
application/json;odata.streaming=false
application/json
application/xml
text/plain
application/octet-stream
text/json
Beta Was this translation helpful? Give feedback.
All reactions
-
These are defined in the OData JSON Format v4.01 specification. streaming
only applies if you are streaming content such as files (ex: images). metadata
controls what, if any, OData metadata is returned. application/json
will always work, but with assumed values for other parameters. Selecting different media types, particularly with metadata
, should produce slightly different responses depending on the API.
Beta Was this translation helpful? Give feedback.
All reactions
-
Okay that's pretty clear, thanks. I found the SwaggerDefaultValues workaround is not really needed? At least in my API project,
// REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1752#issue-663991077 foreach ( var responseType in context.ApiDescription.SupportedResponseTypes ) { // REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/b7cf75e7905050305b115dd96640ddd6e74c7ac9/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs#L383-L387 var responseKey = responseType.IsDefaultResponse ? "default" : responseType.StatusCode.ToString(); var response = operation.Responses[responseKey]; foreach ( var contentType in response.Content.Keys ) { if ( !responseType.ApiResponseFormats.Any( x => x.MediaType == contentType ) ) { response.Content.Remove( contentType ); } } }
if I put a breakpoint on response.Content.Remove
, it is never reached? I did remove all Produces
attributes from my controller, so I guess maybe that's expected. Although I can still see the non-odata media types in Swagger, so I'm confused again. 😄
Beta Was this translation helpful? Give feedback.
All reactions
-
The ODataInputFormatter
and ODataOutputFormatter
get their media types from:
The last few: text/plain
, application/octet-stream
, and text/json
may be coming from another formatter. The reported media types is a union of everything defined. text/json
is a valid, alternative media type, but is hardly used anymore. text/plain
does show up out-of-the-box for return scalar values, even when it might still be valid JSON (it's actually ambiguous). application/octet-stream
is a catch-all, but is usually for files. If you don't use any of these, it might be worth filtering them out.
Beta Was this translation helpful? Give feedback.