Search code examples
c#asp.netodatablazor-server-sideodata-v4

The Odatav4 Expand query not working properly in Blazor server project


When I try to expand the OrdDetails using the expand property in OData, it works properly. However, when I try to access OrdDetailsData, I encounter an error.

1.https://localhost:44324/odata/Orders?$expand=OrdDetails --this one working " {"@odata.context":"https://localhost:44324/odata/$metadata#Orders(OrdDetails())","value":[{"Id":1,"ParentId":1,"HasChild":true,"Summary":"somevalue","Created":"2023-01-23T10:00:08+05:30","OrdDetailsData":{"SecondId":1110},"OrdDetails":{"Id":111}},{"Id":2,"ParentId":2,"HasChild":true,"Summary":"somevalue1","Created":"2023-01-24T10:00:08+05:30","OrdDetailsData":{"SecondId":2220},"OrdDetails":{"Id":222}}]}

2.https://localhost:44324/odata/Orders?$expand=OrdDetailsData "

Same scenario, I am expanding the OrdDetailsData, but I have faced the below error. How to solve this problem?

" {"error":{"code":"","message":"The query specified in the URI is not valid. Property 'OrdDetailsData' on type 'Sirrusss.Client.Order' is not a navigation property or complex property. Only navigation properties can be expanded.","details":[],"innererror":{"message":"Property 'OrdDetailsData' on type 'Sirrusss.Client.Order' is not a navigation property or complex property. Only navigation properties can be expanded.","type":"Microsoft.OData.ODataException","stacktrace":" at Microsoft.OData.UriParser.SelectExpandBinder.ParseComplexTypesBeforeNavigation(IEdmStructuralProperty edmProperty, PathSegmentToken& currentToken, List1 pathSoFar)\r\n at Microsoft.OData.UriParser.SelectExpandBinder.GenerateExpandItem(ExpandTermToken tokenIn)\r\n at System.Linq.Enumerable.SelectEnumerableIterator2.MoveNext()\r\n at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext()\r\n at System.Collections.Generic.List1.InsertRange(Int32 index, IEnumerable`1 collection)\r\n at Microsoft.OData.UriParser.SelectExpandBinder.Bind(ExpandToken expandToken, SelectToken selectToken)\r\n at Microsoft.OData.UriParser.SelectExpandSemanticBinder.Bind(ODataPathInfo odataPathInfo, ExpandToken expandToken, SelectToken selectToken, ODataUriParserConfiguration configuration, BindingState state)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseSelectAndExpandImplementation(String select, String expand, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseSelectAndExpand()\r\n at Microsoft.AspNetCore.OData.Query.SelectExpandQueryOption.get_SelectExpandClause()\r\n at Microsoft.AspNetCore.OData.Query.Validator.SelectExpandQueryValidator.Validate(SelectExpandQueryOption selectExpandQueryOption, ODataValidationSettings validationSettings)\r\n at Microsoft.AspNetCore.OData.Query.SelectExpandQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNetCore.OData.Query.Validator.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ValidateQuery(HttpRequest request, ODataQueryOptions queryOptions)\r\n at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuting(ActionExecutingContext actionExecutingContext)"}}} "

** This is my model class **

 public class Order
 {

     public Order() { }

     public int? Id { get; set; }

     public int? ParentId { get; set; }

     public bool? HasChild { get; set; }

     public string? Summary { get; set; }

     public DateTime? Created { get; set; }
     
     public virtual Details OrdDetails { get; set; }

     public virtual DetailsData OrdDetailsData { get; set; }

 }

public class Details
 {
     public Details() { }

     public int Id { get; set; }
 }

 public class DetailsData
 {

     public DetailsData() { }

     public int SecondId { get; set; }
 }

 


In Program.cs file

using BlazorDataGridODatav4;
using BlazorDataGridODatav4.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.OData;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OData.Edm;
using Microsoft.OData.ModelBuilder;


static IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder();
    builder.Namespace = "Sirrusss.Client";
      var orgUnits = builder.EntitySet<Order>("Orders");
    return builder.GetEdmModel();
}


var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddControllersWithViews().AddOData(opt => { opt.Select().Filter().Count().OrderBy().Expand().SetMaxTop(null).AddRouteComponents("odata", GetEdmModel()); });
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

builder.Services.AddSingleton<WeatherForecastService>();


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();
app.UseCors(x => x
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .SetIsOriginAllowed(origin => true) // allow any origin
                    .AllowCredentials()); // allow credentials

app.MapRazorPages();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

When I try to expand the OrdDetails using the expand property in OData, it works properly. However, when I try to access OrdDetailsData, I encounter an error. Anyone help me how to solve this problem?


Solution

  • Your class DetailsData treated not as Entity, but as ComplexType. And that's why no navigation property added. And only navigation properties can be expanded.

    DetailsData was not made Entity, because by Convention it not contains any Keys. You can fix that by renaming SecondId -> Id or by adding [Key] as attribute:

        [Key]
        public int SecondId { get; set; }