Open VamseeInala opened 4 years ago
Hi, Not sure it is related but more generally I also have trouble using JObject / JsonDocument in Models.
public class Job
{
[Key]
public int Id { get; set; }
...
[Required]
[JsonConverter(typeof(JsonDocumentConverter))]
public JsonDocument Data { get; set; }
// Trick to not serialize RootElement at return
// Without this, having {"prop1": "Val1"} will result in { "rootElement": {"prop1": "Val1"} }
internal sealed class JsonDocumentConverter
: JsonConverter<System.Text.Json.JsonDocument>
{
public override JsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonDocument.ParseValue(ref reader);
}
public override void Write(Utf8JsonWriter writer, JsonDocument value, JsonSerializerOptions options)
{
value.WriteTo(writer);
}
}
And I'm not able to query the JsonDocument using path like:
https://localhost:4003/odata/dashboards?$filter=Data/Prop1 eq 'Val1'
The result is the same using JObject, it looks for accessible properties, but these types mostly works with lookup methods.
I found a way to display specific Json properties doing this:
public class Job
{
// ... ADD PART
// Here is the accessor trick to get specific property value in json
// But still not able to filter using this
[NotMapped]
public string TM
{
get { return Data.RootElement.GetProperty("TM").GetString(); }
}
// Startup.cs EDM model builder to use the new property
builder.StructuralTypes.First(t => t.ClrType == typeof(Job)).AddProperty(typeof(Job).GetProperty("TM"));
So the result looks like:
Just to clarify, this class is used as Npgsql entity and here is how I use it following Npgsql Doc:
private IQueryable<Job> FilterJobs(IQueryable<Job> jobsQuery, JobFilter jobFilter)
{
return jobsQuery.Where(j =>
// Search in some Data tags
j.Data.RootElement.GetProperty("SN").GetString().Contains(jobFilter.Search) ||
j.Data.RootElement.GetProperty("RO").GetString().Contains(jobFilter.Search) ||
...
);
}
Is it something straightforward to do in order to manage such properties or quiet complicated?
any updates regarding this issue? any workarounds?
I am trying to build a ASPNet Core OData API on entities which has complex properties of type anonymous JSON (i.e. 'dynamic' or 'JObject' or object) and a simple GET API fails while serialization of response from the provider.
Assemblies affected
Microsoft.AspNetCore.OData - 7.3.0
Reproduce steps
Expected result
The response would be returned with the dynamic JSON object as one of the properties. The response is returned as expected with using the ODataController.
Actual result
Exception is being logged in the output and the response is half baked. Below are exception details in case of JObject.
System.Runtime.Serialization.SerializationException: ODataResourceSerializer cannot write an object of type 'Collection(Newtonsoft.Json.Linq.JToken)'. at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.GetResourceType(Object graph, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteResource(Object graph, ODataWriter writer, ODataSerializerContext writeContext, IEdmTypeReference expectedType) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteComplexAndExpandedNavigationProperty(IEdmProperty edmProperty, SelectItem selectItem, ResourceContext resourceContext, ODataWriter writer) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteComplexProperties(SelectExpandNode selectExpandNode, ResourceContext resourceContext, ODataWriter writer) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteResource(Object graph, ODataWriter writer, ODataSerializerContext writeContext, IEdmTypeReference expectedType) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSet(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) at Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.WriteToStream(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, IWebApiUrlHelper internaUrlHelper, IWebApiRequestMessage internalRequest, IWebApiHeaders internalRequestHeaders, FuncgLogged|21_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
2 getODataMessageWrapper, Func
2 getEdmTypeSerializer, Func2 getODataPayloadSerializer, Func
1 getODataSerializerContext) at Microsoft.AspNet.OData.Formatter.ODataOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.