C# 如何在OData中禁用OpenTypes的不存在属性
我使用的是开放类型:C# 如何在OData中禁用OpenTypes的不存在属性,c#,odata,C#,Odata,我使用的是开放类型: public class Student { public Guid Id { get; set; } public string Name { get; set; } public IBackpack Backpack { get { return new Backpack() { Id = Guid.NewGuid(
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
public IBackpack Backpack
{
get
{
return new Backpack() { Id = Guid.NewGuid() };
}
set
{
}
}
Dictionary<string, object> interfaces;
public Dictionary<string, object> Interfaces
{
get
{
if (interfaces == null)
{
interfaces = new Dictionary<string, object>
{
{ "Backpack", this.Backpack as Backpack }
};
}
return interfaces;
}
set
{
}
}
}
如何在open types dictionary上不存在属性时返回错误?因此,问题是在Github中产生的: 然而,他们说这是意料之中的。我找到了解决此问题的方法: 我在CreateResource方法中添加了自定义资源序列化程序并验证现有属性:
public class CustomODataResourceSerializer : ODataResourceSerializer
{
public CustomODataResourceSerializer(ODataSerializerProvider serializerProvider) : base(serializerProvider)
{
}
public override ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
{
var resource = base.CreateResource(selectExpandNode, resourceContext);
if (selectExpandNode.SelectedDynamicProperties?.Any() == true)
{
foreach (var dynamicProperty in selectExpandNode.SelectedDynamicProperties)
{
if (!resource.Properties.Any(s => s.Name == dynamicProperty) && resourceContext.DynamicComplexProperties?.Any(s => s.Key == dynamicProperty) != true)
{
throw new InvalidOperationException($"Cannot find property '{dynamicProperty}' on '{resource.TypeName}' entity");
}
}
}
return resource;
}
public override void AppendDynamicProperties(ODataResource resource, SelectExpandNode selectExpandNode, ResourceContext resourceContext)
{
if (selectExpandNode.SelectedDynamicProperties?.Any() == true)
{
base.AppendDynamicProperties(resource, selectExpandNode, resourceContext);
}
}
}
它工作得很好,但是在过滤查询中我遇到了这种问题。因此,我添加了验证方法:
void ValidateOpenType(QueryNode expression)
{
if (expression is BinaryOperatorNode operatorNode)
{
ValidateOpenType(operatorNode.Left);
ValidateOpenType(operatorNode.Right);
}
else if (expression is ConvertNode convertNode)
{
ValidateOpenType(convertNode.Source);
}
else if (expression is SingleValueFunctionCallNode functionCallNode)
{
foreach (var queryNode in functionCallNode.Parameters)
{
ValidateOpenType(queryNode);
}
}
else if (expression is SingleValuePropertyAccessNode singleValueProperty && !string.IsNullOrEmpty(singleValueProperty.Property?.Name))
{
if (singleValueProperty.Source is SingleNavigationNode navigationNode)
{
ThrowExceptionWhenPropertyDoesNotExists(singleValueProperty.Property.Name, navigationNode.NavigationSource.Name);
}
else
{
ThrowExceptionWhenPropertyDoesNotExists(singleValueProperty.Property.Name, typeof(TEntity).Name);
}
}
else if (expression is SingleValueOpenPropertyAccessNode valueOpenPropertyAccessNode)
{
if (valueOpenPropertyAccessNode.Source is SingleNavigationNode navigationNode)
{
ThrowExceptionWhenPropertyDoesNotExists(valueOpenPropertyAccessNode.Name, navigationNode.NavigationSource.Name);
}
else
{
ThrowExceptionWhenPropertyDoesNotExists(valueOpenPropertyAccessNode.Name, typeof(TEntity).Name);
}
}
}
void ThrowExceptionWhenPropertyDoesNotExists(string propertyName, string entityName)
{
if (ModelClasses.Any(t => t.Name == entityName && t.GetProperty(propertyName) == null))
{
throw new InvalidOperationException($"Could not find a property named '{propertyName}' on '{entityName}' entity");
}
}
上课:
List<Type> modelClasses;
public List<Type> ModelClasses
{
get
{
if (modelClasses == null)
{
modelClasses = GetClasses("ODataCoreTest");
}
return modelClasses;
}
}
static List<Type> GetClasses(string nameSpace)
{
Assembly asm = Assembly.GetExecutingAssembly();
List<Type> namespacelist = new List<Type>();
List<Type> classlist = new List<Type>();
foreach (Type type in asm.GetTypes())
{
if (type.Namespace == nameSpace)
namespacelist.Add(type);
}
foreach (Type classType in namespacelist)
classlist.Add(classType);
return classlist;
}
列出模型类;
公共列表模型类
{
得到
{
if(modelClasses==null)
{
modelClasses=GetClasses(“ODataCoreTest”);
}
返回模型类;
}
}
静态列表GetClass(字符串命名空间)
{
Assembly asm=Assembly.getExecutionGassembly();
列表名称空间列表=新列表();
List classlist=新列表();
foreach(在asm.GetTypes()中键入Type)
{
if(type.Namespace==名称空间)
名称空间列表。添加(类型);
}
foreach(名称空间列表中的类型classType)
classlist.Add(classType);
返回类列表;
}
用法:
[HttpGet]
public IActionResult Get(ODataQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken)
{
if (queryOptions.Filter?.FilterClause != null)
{
ValidateOpenType(queryOptions.Filter.FilterClause.Expression);
}
var res = new List<Student>() { CreateNewStudent() };
return Ok(res);
}
[HttpGet]
公共IActionResult Get(ODataQueryOptions查询选项、取消令牌取消令牌)
{
if(queryOptions.Filter?.FilterClause!=null)
{
ValidatePenType(queryOptions.Filter.FilterClause.Expression);
}
var res=new List(){CreateNewStudent()};
返回Ok(res);
}
List<Type> modelClasses;
public List<Type> ModelClasses
{
get
{
if (modelClasses == null)
{
modelClasses = GetClasses("ODataCoreTest");
}
return modelClasses;
}
}
static List<Type> GetClasses(string nameSpace)
{
Assembly asm = Assembly.GetExecutingAssembly();
List<Type> namespacelist = new List<Type>();
List<Type> classlist = new List<Type>();
foreach (Type type in asm.GetTypes())
{
if (type.Namespace == nameSpace)
namespacelist.Add(type);
}
foreach (Type classType in namespacelist)
classlist.Add(classType);
return classlist;
}
[HttpGet]
public IActionResult Get(ODataQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken)
{
if (queryOptions.Filter?.FilterClause != null)
{
ValidateOpenType(queryOptions.Filter.FilterClause.Expression);
}
var res = new List<Student>() { CreateNewStudent() };
return Ok(res);
}