未调用 ASP.NET Core 类型转换器方法

man*_*ger 1 typeconverter asp.net-core-2.0

我正在尝试配置ForwardedHeadersOptions哪些是Microsoft.AspNetCore.HttpOverrides. 我已将选项添加到我的appsettings.json

"ForwardedHeadersOptions": {
        "ForwardedHeaders": 5,
        "ForwardLimit": 1,
        "KnownProxies": [
            "111.111.111.111"
        ]
    },
Run Code Online (Sandbox Code Playgroud)

前两个属性(ForwardedHeadersForwardLimit)已正确映射,而则KnownProxies不是。这是预期的,因为 的类型KnownProxiesIList<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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我注册了IPAddressTypeConverter这样Startup.cs的:

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

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

Ott*_*ell 7

当配置框架尝试转换 appsettings 文件中的字符串时,它会从字符串进行转换。您的 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);
    }
Run Code Online (Sandbox Code Playgroud)

然后,在 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);
            }
        });
Run Code Online (Sandbox Code Playgroud)

我尝试为 KnownNetworks 制作一个类似的类型转换器,但它没有坚持下来,可能是因为输入(字符串/整数)。因此,我最终创建了一个单独的 IPNetworkSettingClass,其中前缀字段是字符串而不是 IPAdress 类的对象。然后我可以使用以下方法从 appsettings 获取网络:

 var knownNetworks = Configuration.GetSection("ForwardedHeadersOptions").GetSection("KnownNetworks").Get<List<IPNetworkSetting>>();
Run Code Online (Sandbox Code Playgroud)

最后,我在绑定的 ForwardedHeadersOptions 实例中以编程方式设置 KnownNetworks。

希望这可以帮助

  • 检查“String”类型是否多余。`string` 和 `String` 在类型相等方面是相同的。 (4认同)