简体   繁体   English

自定义属性类型的Model Binder

[英]Model Binder for a custom property type

On an ASP.NET Core project I have the following action: 在ASP.NET Core项目上,我有以下操作:

public async Task<IActionResult> Get(ProductModel model) {
}

public class ProductModel {
  public Filter<Double> Price { get; set; }
}    

I have a Filter base class and a RangeFilter as follows: 我有一个Filter基类和一个RangeFilter,如下所示:

public class Filter<T> { }

public class RangeFilter<T> : Filter<T> { 
  public abstract Boolean TryParse(String value, out Filter<T> filter);  
}

I am passing a String ( "[3.34;18.75]" ) to the Action as Price. 我正在将String( "[3.34;18.75]" )作为价格传递给Action。

I need to create a ModelBinder where I use the TryParse method to try to convert that String into a RangeFilter<Double> to define the ProductModel.Price property. 我需要创建一个ModelBinder ,在其中使用TryParse方法尝试将该String转换为RangeFilter<Double>以定义ProductModel.Price属性。

If TryParse fails, eg, returns false then the ProductModel.Price property becomes null. 如果TryParse失败,例如返回falseProductModel.Price属性将为null。

How can this be done? 如何才能做到这一点?

If you're willing to move the parsing method into a static class, this would become a bit more feasible. 如果您愿意将解析方法移到静态类中,这将变得更加可行。

Parser 解析器

public static class RangeFilterParse
{
    public static Filter<T> Parse<T>(string value)
    {
        // parse the stuff!
        return new RangeFilter<T>();
    }
}

public abstract class Filter<T> { }

public class RangeFilter<T> : Filter<T> { }

Model 模型

public class ProductModel
{
    [ModelBinder(BinderType = typeof(RangeModelBinder))]
    public Filter<double> Price { get; set; }
}

Binder 活页夹

public class RangeModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        try
        {
            var input = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ToString();
            var inputType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];

            // invoke generic method with proper type
            var method = typeof(RangeFilterParse).GetMethod(nameof(RangeFilterParse.Parse), BindingFlags.Static);
            var generic = method.MakeGenericMethod(inputType);
            var result = generic.Invoke(this, new object[] { input });

            bindingContext.Result = ModelBindingResult.Success(result);
            return Task.CompletedTask;
        }
        catch(Exception) // or catch a more specific error related to parsing
        {
            bindingContext.Result = ModelBindingResult.Success(null);
            return Task.CompletedTask;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM