4

I have the following model

public class Dog
{
    public string NickName { get; set; }
    public int Color { get; set; }
}

and I have the following api controller method which is exposed through an API

public class DogController : ApiController
{
  // GET /v1/dogs
  public IEnumerable<string> Get([FromUri] Dog dog)
  { ...}

Now, I would like to issue the GET request as follows:

GET http://localhost:90000/v1/dogs?nick_name=Fido&color=1

Question: How do I bind the query string parameter nick_name to property NickName in the dog class? I know I can call the API without the underscore (i.e. nickname) or change NickName to Nick_Name and get the value, but I need the names to remain like that for convention.

Edit This question is not a duplicate because it is about ASP.NET WebApi not ASP.NET MVC 2

2
  • Your question is about Binding a model property to an alias, correct? This answer on that post does exactly that. Commented Oct 21, 2015 at 0:12
  • 1
    There is a difference between implementing System.Web.Mvc.IModelBinder and System.Web.Http.ModelBinding.IModelBinder. BindModel for MVC is [object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)] and for WebApi is [bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)]. The examples I see in your possible duplicate only cover MVC not WebApi Commented Oct 21, 2015 at 0:32

1 Answer 1

4

Implementing the IModelBinder,

public class DogModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(Dog))
        {
            return false;
        }

        var model = (Dog)bindingContext.Model ?? new Dog();


        var hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);

        var searchPrefix = (hasPrefix) ? bindingContext.ModelName + "." : "";

        model.NickName = GetValue(bindingContext, searchPrefix, "nick_name");

        int colorId = 0;
        if (int.TryParse(GetValue(bindingContext, searchPrefix, "colour"), out colorId))
        {
            model.Color = colorId; // <1>
        }

        bindingContext.Model = model;

        return true;
    }

    private string GetValue(ModelBindingContext context, string prefix, string key)
    {
        var result = context.ValueProvider.GetValue(prefix + key); // <4>
        return result == null ? null : result.AttemptedValue;
    }
}

And Create ModelBinderProvider,

public class DogModelBinderProvider : ModelBinderProvider
{
    private CollectionModelBinderProvider originalProvider = null;

    public DogModelBinderProvider(CollectionModelBinderProvider originalProvider)
    {
        this.originalProvider = originalProvider;
    }

    public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
    {
        // get the default implementation of provider for handling collections
        IModelBinder originalBinder = originalProvider.GetBinder(configuration, modelType);

        if (originalBinder != null)
        {
            return new DogModelBinder();
        }

        return null;
    }
}

and using in controller something like,

public IEnumerable<string> Get([ModelBinder(typeof(DogModelBinder))] Dog dog)
{
    //controller logic
}
Sign up to request clarification or add additional context in comments.

1 Comment

how can use this method for array type property?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.