Return null in OData operations, results in different errors
@Nthemba is already working on this.
Since Jul 12, 2022.
- Dominant language
- C#
- Stars
- 505
- Forks
- 186
- PR merge metrics
- No merged PRs in 30d
Description
Hello, I encountered ome problems when returning null in OData operations (actions and functions). I cannot provide my actual code, so I made a sample project which result in similar errors.
Here the sample code using Microsoft.AspNetCore.OData 8.0.10 followed with some of the errors which I encountered with this sample project.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddOData(options =>
{
var builder = new ODataConventionModelBuilder();
builder.Namespace = "MyNamespace";
var entityType = builder.EntitySet<Article>("Articles").EntityType.Collection;
var function = entityType.Function("GetName");
function.Returns<string>();
var function2 = entityType.Function("GetEntity");
function2.ReturnsFromEntitySet<Article>("Articles");
var action1 = entityType.Action("GetEntityAction");
action1.ReturnsFromEntitySet<Article>("Articles");
options.AddRouteComponents("odata", builder.GetEdmModel());
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseODataRouteDebug();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
public class ArticlesController : ODataController
{
[HttpGet]
public IQueryable<Article> Get()
{
var articles = new List<Article> { new Article { Id = 100, Name = "First" } };
return articles.AsQueryable();
}
[HttpGet]
public string GetName() => null;
[HttpGet]
public Article GetEntity() => null;
[HttpPost]
public Article GetEntityAction(ODataActionParameters parameters) => null;
}
public class Article
{
public int Id { get; set; }
public string Name { get; set; }
}
Calling the GetEntity(): Article function results in the following exception and same with the GetEntityAction(): Article:
GET http://localhost:32345/odata/Articles/GetEntity()
GET http://localhost:5000/odata/Articles/GetEntityAction
System.Runtime.Serialization.SerializationException: Cannot serialize a null 'Resource'.
at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInlineAsync(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectAsync(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Calling the GetName(): string function results in the following response:
http://localhost:32345/odata/Articles/GetName()
Response in IIS profile:
{
"@odata.context": "http://localhost:32345/odata/$metadata#Edm.Null"
And no response in Kestrel profile but this exception inside the console:
Microsoft.OData.ODataException: Cannot write the value 'null' in top level property; return 204 instead.
at Microsoft.OData.WriterValidator.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, Boolean isTopLevel, IEdmModel model)
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteNullPropertyAsync(ODataPropertyInfo property)
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WritePropertyAsync(ODataProperty property, IEdmStructuredType owningType, Boolean isTopLevel, IDuplicatePropertyNameChecker duplicatePropertyNameChecker, ODataResourceMetadataBuilder metadataBuilder)
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.<>c__DisplayClass9_0.<<WriteTopLevelPropertyAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.OData.JsonLight.ODataJsonLightSerializer.WriteTopLevelPayloadAsync(Func`1 payloadWriterFunc)
at Microsoft.OData.JsonLight.ODataJsonLightOutputContext.WritePropertyImplementationAsync(ODataProperty property)
at Microsoft.OData.JsonLight.ODataJsonLightOutputContext.WritePropertyAsync(ODataProperty property)
at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataPrimitiveSerializer.WriteObjectAsync(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Note the missing end bracket? Also I would expect "value": null or like the exception said a 204. This happends when using the IISExpress profile.
Using the Kestrel profile does not return a response, which is easily reproduced with WireShark.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.