Microsoft OData 通过依赖注入自定义 ODataWriterSettings

Posted

技术标签:

【中文标题】Microsoft OData 通过依赖注入自定义 ODataWriterSettings【英文标题】:Microsoft OData Customising ODataWriterSettings through dependency injection 【发布时间】:2022-01-11 13:46:48 【问题描述】:

我需要更改 odata 写入器设置,以便当写入的对象不符合架构时,它会继续写入,而不是在验证标记为必需的空属性时抛出错误。

代码如下:

var writerSettings = new ODataMessageWriterSettings();
writerSettings.Validations = ValidationKinds.None;

我需要 Microsoft.AspNetCore OData 消息编写器才能使用这些设置。但是当 ODataMessageWriter 被实例化时,它没有这些设置。 当我在 ODataMessageWriter 构造函数中调试并设置断点时,我可以更改设置并获得所需的结果。

writerSettings.Validations = ValidationKinds.ThrowOnDuplicatePropertyNames | ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; // This is the desired setting.

我注意到我们定义并注入了以下类,

public class MyODataRoutingApplicationModelProvider : IApplicationModelProvider

    public MyODataRoutingApplicationModelProvider(
        IOptions<ODataOptions> options)
    
        options.Value.AddRouteComponents("odata/datasource/COMPANY_CODE", EdmCoreModel.Instance);
    

我是否需要更改此模型提供程序以使其使用这些设置?

以下异常是我试图解决的最初问题。更改数据层/edm 模型/架构似乎不是我们希望特定于我们的解决方案/数据库架构的可行选项。

Microsoft.OData.ODataException:“Edm.DateTimeOffset”类型的属性“ImpArrivalDate[Nullable=False]”具有空值,这是不允许的。 在 Microsoft.OData.WriterValidationUtils.ValidateNullPropertyValue(IEdmTypeReference 预期PropertyTypeReference,字符串 propertyName,IEdmModel 模型) 在 Microsoft.OData.WriterValidator.ValidateNullPropertyValue(IEdmTypeReference 预期PropertyTypeReference,字符串 propertyName,布尔 isTopLevel,IEdmModel 模型) 在 Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteNullProperty(ODataPropertyInfo 属性) 在 Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperty(ODataProperty 属性,IEdmStructuredType owningType,布尔 isTopLevel,IDuplicatePropertyNameChecker duplicatePropertyNameChecker,ODataResourceMetadataBuilder metadataBuilder) 在 Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties(IEdmStructuredType owningType,IEnumerable`1 属性,布尔 isComplexValue,IDuplicatePropertyNameChecker duplicatePropertyNameChecker,ODataResourceMetadataBuilder metadataBuilder) 在 Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource(ODataResource 资源) 在 Microsoft.OData.ODataWriterCore.c__DisplayClass123_0.b__0()

该属性被标记为必需但可以为空,如扩展类 (ConsignmentAllHeaderXpo) 中所示:

[XmlIgnore]
        [Delayed]
        [PersistentAlias("ShipmentDate")]
        [Template(typeof(HardDate1))]
        [Display(Name = "Arr.Date", Description = "Import Arrival Date")]
        [Description("Import Arrival Date")]
        [Required(ErrorMessage = "Field Arr.Date is required")]
        [RpsHelp(Text = "Expected Arrival Date")]
        public DateTime? ImpArrivalDate
        
            get  return GetValue<DateTime?>(null, nameof(ImpArrivalDate)); 
            set  ShipmentDate = value; OnPropertyChanged(nameof(ImpArrivalDate)); 
        

【问题讨论】:

【参考方案1】:

我发现在控制器的操作中更改处理请求时需要使用的编写器设置是有效的:

[EnableQuery(PageSize = 1000)]
public IActionResult Get([FromRoute] string COMPANY_CODE)

    // Get entity set's EDM type: A collection type.
    ODataPath path = Request.ODataFeature().Path;
    IEdmCollectionType collectionType = (IEdmCollectionType)path.Last().EdmType;
    
    IEdmEntityTypeReference entityType = collectionType.ElementType.AsEntity();

    // Setting validation settings on the request to not throw when writing a json response representation is solving the problem.
    // It stops validation errors occuring if the data does not conform to the schema.
    Request.GetWriterSettings().Validations = Microsoft.OData.ValidationKinds.ThrowOnDuplicatePropertyNames | Microsoft.OData.ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;
    string myType = entityType.ShortQualifiedName();
    Type xpoType = DataAccess.GetNameSpaceType(myType);
    var res = GetIQueryable(xpoType, COMPANY_CODE, false);
    return Ok(res);

【讨论】:

以上是关于Microsoft OData 通过依赖注入自定义 ODataWriterSettings的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

WebAPI 2.2 中没有命名空间的 OData v4 自定义函数

Microsoft.AspNet.WebApi.OData 与 Microsoft.Data.OData 和 Microsoft.AspNet.OData 有啥区别?

使用自定义 Doctrine 2 数据类型的依赖注入

使用自定义 Doctrine 2 hydrator 进行依赖注入

Angularjs 自定义过滤器和依赖注入