Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion sample/ODataRoutingSample/ODataRoutingSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.6" />
<PackageReference Include="Microsoft.OData.Edm" Version="8.2.3" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
<PackageReference Include="Microsoft.OpenApi.OData" Version="1.6.9" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.OData.ModelBuilder" Version="2.0.0" />
<PackageReference Include="Microsoft.OData.Core" Version="8.2.3" />
<PackageReference Include="Microsoft.OData.Edm" Version="8.2.3" />
<PackageReference Include="Microsoft.Spatial" Version="8.2.3" />
<PackageReference Include="Microsoft.OData.Core" Version="8.4.0" />
<PackageReference Include="Microsoft.OData.Edm" Version="8.4.0" />
<PackageReference Include="Microsoft.Spatial" Version="8.4.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,14 +307,20 @@ private Expression BindIsOf(SingleValueFunctionCallNode node)
return FalseConstant;
}

string typeName = (string)((ConstantNode)node.Parameters.Last()).Value;
IEdmTypeReference edmTypeReference = null;
QueryNode queryNode = node.Parameters.Last();
if (queryNode is ConstantNode constantNode)
{
edmTypeReference = Model.FindType((string)constantNode.Value)?.ToEdmTypeReference(false);
}
else if (queryNode is SingleResourceCastNode singleResourceCastNode)
{
edmTypeReference = singleResourceCastNode.TypeReference;
}

IEdmType edmType = Model.FindType(typeName);
Type clrType = null;
if (edmType != null)
if (edmTypeReference != null)
{
// bool nullable = source.Type.IsNullable();
IEdmTypeReference edmTypeReference = edmType.ToEdmTypeReference(false);
clrType = Model.GetClrType(edmTypeReference);
}

Expand Down Expand Up @@ -715,13 +721,21 @@ private Expression BindCastSingleValue(SingleValueFunctionCallNode node)
Contract.Assert(arguments.Length == 1 || arguments.Length == 2);

Expression source = arguments.Length == 1 ? this.Parameter : arguments[0];
string targetTypeName = (string)((ConstantNode)node.Parameters.Last()).Value;
IEdmType targetEdmType = Model.FindType(targetTypeName);
Type targetClrType = null;

if (targetEdmType != null)
IEdmTypeReference targetEdmTypeReference = null;
QueryNode queryNode = node.Parameters.Last();
if (queryNode is ConstantNode constantNode)
{
targetEdmTypeReference = Model.FindType((string)constantNode.Value)?.ToEdmTypeReference(false);
}
else if (queryNode is SingleResourceCastNode singleResourceCastNode)
{
targetEdmTypeReference = singleResourceCastNode.TypeReference;
}

Type targetClrType = null;
if (targetEdmTypeReference != null)
{
IEdmTypeReference targetEdmTypeReference = targetEdmType.ToEdmTypeReference(false);
targetClrType = Model.GetClrType(targetEdmTypeReference);

if (source != NullConstant)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,13 +567,22 @@ protected virtual Expression BindCastSingleValue(SingleValueFunctionCallNode nod
Contract.Assert(arguments.Length == 1 || arguments.Length == 2);

Expression source = arguments.Length == 1 ? context.CurrentParameter : arguments[0];
string targetTypeName = (string)((ConstantNode)node.Parameters.Last()).Value;
IEdmType targetEdmType = context.Model.FindType(targetTypeName);

IEdmTypeReference targetEdmTypeReference = null;
QueryNode queryNode = node.Parameters.Last();
if (queryNode is ConstantNode constantNode)
{
targetEdmTypeReference = context.Model.FindType((string)constantNode.Value)?.ToEdmTypeReference(false);
}
else if (queryNode is SingleResourceCastNode singleResourceCastNode)
{
targetEdmTypeReference = singleResourceCastNode.TypeReference;
}

Type targetClrType = null;

if (targetEdmType != null)
if (targetEdmTypeReference != null)
{
IEdmTypeReference targetEdmTypeReference = targetEdmType.ToEdmTypeReference(false);
targetClrType = context.Model.GetClrType(targetEdmTypeReference);

if (source != NullConstant)
Expand Down Expand Up @@ -650,14 +659,20 @@ protected virtual Expression BindIsOf(SingleValueFunctionCallNode node, QueryBin
return FalseConstant;
}

string typeName = (string)((ConstantNode)node.Parameters.Last()).Value;
IEdmTypeReference edmTypeReference = null;
QueryNode queryNode = node.Parameters.Last();
if (queryNode is ConstantNode constantNode)
{
edmTypeReference = context.Model.FindType((string)constantNode.Value)?.ToEdmTypeReference(false);
}
else if (queryNode is SingleResourceCastNode singleResourceCastNode)
{
edmTypeReference = singleResourceCastNode.TypeReference;
}

IEdmType edmType = context.Model.FindType(typeName);
Type clrType = null;
if (edmType != null)
if (edmTypeReference != null)
{
// bool nullable = source.Type.IsNullable();
IEdmTypeReference edmTypeReference = edmType.ToEdmTypeReference(false);
clrType = context.Model.GetClrType(edmTypeReference);
}

Expand Down
12 changes: 5 additions & 7 deletions src/Microsoft.AspNetCore.OData/Query/Expressions/QueryBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -664,27 +664,25 @@ public virtual Expression BindSingleResourceCastFunctionCall(SingleResourceFunct

IEdmModel model = context.Model;

string targetEdmTypeName = null;
IEdmTypeReference targetEdmType = null;
QueryNode queryNode = node.Parameters.Last();
if (queryNode is ConstantNode constantNode)
{
targetEdmTypeName = constantNode.Value as string;
targetEdmType = model.FindType((string)constantNode.Value)?.ToEdmTypeReference(false);
}
else if (queryNode is SingleResourceCastNode singleResourceCastNode)
{
targetEdmTypeName = singleResourceCastNode.TypeReference.FullName();
targetEdmType = singleResourceCastNode.TypeReference;
}
else
{
throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, queryNode.Kind, "BindSingleResourceCastFunctionCall");
throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, queryNode.Kind, nameof(BindSingleResourceCastFunctionCall));
}

IEdmType targetEdmType = model.FindType(targetEdmTypeName);
Type targetClrType = null;

if (targetEdmType != null)
{
targetClrType = model.GetClrType(targetEdmType.ToEdmTypeReference(false));
targetClrType = model.GetClrType(targetEdmType);
}

if (arguments[0].Type == targetClrType)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// <copyright file="IsOfAndCastController.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;

namespace Microsoft.AspNetCore.OData.E2E.Tests.IsOfAndCast;

public class IsOfAndCastController : ODataController
{
private static IsOfAndCastDataSource _dataSource = new IsOfAndCastDataSource();

[EnableQuery]
[HttpGet("odata/products")]
public IActionResult GetProducts()
{
return Ok(_dataSource.Products);
}

[EnableQuery]
[HttpGet("odata/orders")]
public IActionResult GetOrders()
{
return Ok(_dataSource.Orders);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// <copyright file="IsOfAndCastDataModel.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Microsoft.AspNetCore.OData.E2E.Tests.IsOfAndCast;

public class Product
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public Domain Domain { get; set; }
public Double Weight { get; set; }
}

[Flags]
public enum Domain
{
Military = 1,
Civil = 2,
Both = 3,
}

public class AirPlane : Product
{
public int Speed { get; set; }
public string Model { get; set; }
}

public class JetPlane : AirPlane
{
public string JetType { get; set; }
}

public class Order
{
[Key]
public int OrderID { get; set; }
public Address Location { get; set; }
public IList<Product> Products { get; set; }
}

public class Address
{
public string City { get; set; }
}

public class HomeAddress : Address
{
public string HomeNo { get; set; }
}

public class OfficeAddress : Address
{
public string OfficeNo { get; set; }
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// <copyright file="IsOfAndCastDataSource.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using System.Collections.Generic;

namespace Microsoft.AspNetCore.OData.E2E.Tests.IsOfAndCast;

public class IsOfAndCastDataSource
{
public IsOfAndCastDataSource()
{
ResetData();
InitializeData();
}

private void ResetData()
{
this.Products?.Clear();
this.Orders?.Clear();
}

public IList<Product> Products { get; private set; }
public IList<Order> Orders { get; private set; }

private void InitializeData()
{
this.Products = new List<Product>
{
new Product
{
ID = 1,
Name = "Product1",
Domain = Domain.Civil,
Weight = 1000
},
new Product
{
ID = 2,
Name = "Product2",
Domain = Domain.Military,
Weight = 2000,
},
new AirPlane
{
ID = 3,
Name = "Product3",
Domain = Domain.Both,
Weight = 1500,
Speed = 900,
Model = "Boeing 737"
},
new JetPlane
{
ID = 4,
Name = "Product4",
Domain = Domain.Civil,
Weight = 1200,
Speed = 1000,
Model = "Airbus A320",
JetType = "Turbofan"
},
new JetPlane
{
ID = 5,
Name = "Product5",
Domain = Domain.Military,
Weight = 1800,
Speed = 1500,
Model = "F-22 Raptor",
JetType = "Afterburning Turbofan"
}
};

this.Orders = new List<Order>
{
new Order
{
OrderID = 1,
Location = new Address { City = "City1" },
Products = new List<Product> { this.Products[0], this.Products[2] }
},
new Order
{
OrderID = 2,
Location = new HomeAddress { City = "City2", HomeNo = "100NO" },
Products = new List<Product> { this.Products[1], this.Products[3], this.Products[4] }
},
new Order
{
OrderID = 3,
Location = new OfficeAddress { City = "City3", OfficeNo = "300NO" },
Products = new List<Product> { this.Products[0], this.Products[2], this.Products[3] }
},
new Order
{
OrderID = 4,
Location = new HomeAddress { City = "City4", HomeNo = "200NO" },
Products = new List<Product> { this.Products[1], this.Products[4] }
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// <copyright file="IsOfAndCastEdmModel.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using Microsoft.OData.Edm;
using Microsoft.OData.ModelBuilder;

namespace Microsoft.AspNetCore.OData.E2E.Tests.IsOfAndCast;

public class IsOfAndCastEdmModel
{
public static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Order>("Orders");
builder.EntitySet<Product>("Products");
var airPlaneType = builder.EntityType<AirPlane>();
airPlaneType.DerivesFrom<Product>();

builder.Namespace = typeof(Product).Namespace;
return builder.GetEdmModel();
}
}
Loading