Create Property Model Binder in Web API
Asked Answered
E

1

6

I have created ModelBinder for a complex class. I would like to reuse this ModelBinder on a property. So is it possible to use ModelBinder on a property in Web API. I'm searching for an sample implementation which provides property binder like in an MVC. Below is the reference link which i came across but those implementation is for MVC. Any help appreciated.

Reference Link 1

Reference Link 2

Eyrie answered 23/5, 2014 at 7:6 Comment(0)
P
2

I had the same goal, however didn't find the appropriate solution to parse the exact property using binder, and not the whole model. However, there is a solution which more or less suites me - it acts pretty in same way, but requires to mark the model with attribute. I know I'm a bit late, but maybe will help someone with the same issue.

The solution is to use the custom TypeConverter for the required type. First of all, decide how you would like to parse your model. In my example, I need to parse search condition somehow, so my complex model is:

[TypeConverter(typeof(OrderModelUriConverter))] // my custom type converter, which is described below
public class OrderParameter
{
    public string OrderBy { get; set; }
    public int OrderDirection { get; set; }
}

public class ArticlesSearchModel
{
    public OrderParameter Order { get; set; }
    // whatever else
}

Then decide how would you like to parse the input. In my case I simply split the values by comma.

public class OrderParameterUriParser
{
    public bool TryParse(string input, out OrderParameter result)
    {
        result = null;
        if (string.IsNullOrWhiteSpace(input))
        {
            return false;
        }
        var parts = input.Split(',');
        result = new OrderParameter();
        result.OrderBy = parts[0];
        int orderDirection;
        if (parts.Length > 1 && int.TryParse(parts[1], out orderDirection))
        {
            result.OrderDirection = orderDirection;
        }
        else
        {
            result.OrderDirection = 0;
        }
        return true;
    }
}

Then create a converter which will take the part of query and convert it to your model using the above rules.

public class OrderModelUriConverter : TypeConverter
{
    private static readonly Type StringType = typeof (string);

    public OrderModelUriConverter()
    {
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == StringType)
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        var str = value as string;
        if (str != null)
        {
            var parser = new OrderParameterParser()
            OrderParameter orderParameter;
            if (parser.TryParse(str, out orderParameter))
            {
                return orderParameter;
            }
        }
        return base.ConvertFrom(context, culture, value);
    }
}

The usage of the converter is specified in the first sample. Since you are parsing URI, don't forget to add also [FromUri] attribute to your parameter in controller's method.

[HttpGet]
public async Task<HttpResponseMessage> Search([FromUri] ArticlesSearchModel searchModel) // the type converter will be applied only to the property of the types marked with our attribute
{
    // do search
}

Also, you can take a look at this excellent article, which contains similar example and also several other ways of parsing parameters.

Particularism answered 15/2, 2017 at 13:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.