Reputation: 39524
On an ASP.NET Core project I have the following action:
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:
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.
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.
If TryParse
fails, e.g., returns false
then the ProductModel.Price
property becomes null.
How can this be done?
Upvotes: 9
Views: 1803
Reputation: 10889
If you're willing to move the parsing method into a static class, this would become a bit more feasible.
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> { }
public class ProductModel
{
[ModelBinder(BinderType = typeof(RangeModelBinder))]
public Filter<double> Price { get; set; }
}
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;
}
}
}
Upvotes: 5