【问题标题】:ASP Core type converterASP Core 类型转换器
【发布时间】:2019-08-12 11:30:07
【问题描述】:

我正在尝试配置ForwardedHeadersOptions,它是Microsoft.AspNetCore.HttpOverrides 的一部分。我在appsettings.json 中添加了选项

"ForwardedHeadersOptions": {
        "ForwardedHeaders": 5,
        "ForwardLimit": 1,
        "KnownProxies": [
            "111.111.111.111"
        ]
    },

前两个属性(ForwardedHeadersForwardLimit)被正确映射,而 KnownProxies 不是。这是预期的,因为KnownProxies 的类型是IList<IPAddress>。 所以,为了映射这个属性,我创建了类型转换器:

public class IPAddressTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return base.ConvertFrom(context, culture, value);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(IPAddress) || base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (value != null && value is string)
        {
            return IPAddress.Parse(value.ToString());
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

然后,我在Startup.cs 中注册了IPAddressTypeConverter,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    TypeDescriptor.AddAttributes(typeof(ForwardedHeadersOptions), new TypeConverterAttribute(typeof(IPAddressTypeConverter)));
    services.Configure<ForwardedHeadersOptions>(Configuration.GetSection(nameof(ForwardedHeadersOptions)));
 }

但是当我启动应用类型转换器方法时,永远不会被调用。 知道这里有什么问题吗?

【问题讨论】:

    标签: asp.net-core-2.0 typeconverter


    【解决方案1】:

    当配置框架尝试转换 appsettings 文件中的字符串时,它会转换 FROM 字符串。您的 TypeConverter 已注册以处理它将转换为的特定类型(IPAddress)。但它不需要测试这种类型。

    [Can]ConvertTo 方法用于序列化,即将注册的类型转换为另一种类型,如字符串。

    所以,你的类型转换器应该是这样的:

    public class IPAddressTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string) || sourceType == typeof(String))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
    
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value != null && (value is string || value is String))
            {
                return IPAddress.Parse((string)value);
            }
            return base.ConvertFrom(context, culture, value);
        }
    
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
            return base.CanConvertTo(context, destinationType);
        }
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string) && value is IPAddress)
            {
                return ((IPAddress)value).ToString();
            }
    
            return base.ConvertTo(context, culture, value, destinationType);
        }
    

    然后,在 Startup.cs 中,ConfigureServices(),为了清晰和调试断点机会而添加了几行:

            TypeDescriptor.AddAttributes(typeof(IPAddress), new TypeConverterAttribute(typeof(IPAddressTypeConverter)));
    
            var forwardedHeadersOptions = new ForwardedHeadersOptions();
            var forwardedHeadersSection = Configuration.GetSection("ForwardedHeadersOptions");
            forwardedHeadersSection.Bind(forwardedHeadersOptions);
            services.Configure<ForwardedHeadersOptions>(o =>
            {
                o.ForwardedHeaders = ForwardedHeaders.All;
                o.ForwardLimit = forwardedHeadersOptions.ForwardLimit;
                foreach(var knownProxy in forwardedHeadersOptions.KnownProxies)
                {
                    o.KnownProxies.Add(knownProxy);
                }
                foreach(var knownNetwork in forwardedHeadersOptions.KnownNetworks)
                {
                    o.KnownNetworks.Add(knownNetwork);
                }
            });
    

    我尝试为 KnownNetworks 制作一个类似的类型转换器,但它没有成功,可能是因为类型 (string / int)。所以我最终创建了一个单独的 IPNetworkSettingClass,其中前缀字段是字符串而不是 IPAdress 类的对象。然后我可以使用以下命令从 appsettings 中获取网络:

     var knownNetworks = Configuration.GetSection("ForwardedHeadersOptions").GetSection("KnownNetworks").Get<List<IPNetworkSetting>>();
    

    最后我在绑定的 ForwardedHeadersOptions-instance 中以编程方式设置 KnownNetworks。

    希望对你有帮助

    【讨论】:

    • 我离解决方案只有一步之遥,但从未找到它。你的解释很有用。谢谢你,先生!
    • 检查类型是否为String 是多余的。 stringString 在类型相等方面是相同的。
    猜你喜欢
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    相关资源
    最近更新 更多