Automatically binding another parameter in WebAPI

In MVC, such things are pretty trivial. Say I have an MVC action signature:

public ActionResult SomeAction(InjectedObject a, ConstructedObject b)

And let's say that the request from the client contains ConstructedObject, and I want to automatically create InjectedObjectin the pipeline. (This example InjectedObjectis on a lot of actions, maybe even all.) I could just create InjectedObjectModelBinder : IModelBinderand register an instance of this binder when the application starts.

This binder will just instantiate InjectedObject, but I need to. (From the request data, from some other source, a combination of sources, etc.). This worked very well for cross-cutting issues.


However, is there a way to do this in the WebAPI? There is a new one IModelBinder, but it seems that its use involves only one model at the input. And my Googling has so far pointed to this assumption. Is it even possible to inject something into the pipeline in WebAPI, like this, as a cross-cutting issue, while still having a model built from the message body?

The specific use case here is that I would like to create a custom object related to authorization, in this case from request headers. I could create it in action, but all actions will have to. I could add an extension method to the controller, but that would hurt unit testing. The preferred way would be to simply enter it into the pipeline so that I can enter the layout when the module tested the controller actions.

WebAPI ? , , ?

+4
1

, IModelBinder , , , () InjectedObject. , "your_key":

public class InjectedObjectModelBinder : IModelBinder
{
    public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(InjectedObject))
        {
            return false;
        }

        IEnumerable<string> values;
        string keyValue = "";

        if (actionContext.Request.Headers.TryGetValues("your_key", out values))
        {
            keyValue = values.First();
        }

        bindingContext.Model = new InjectedObject() { Id = 789, Name = keyValue };

        return true;
    }
}

InjectedObject. : -, :

public void Post([ModelBinder(typeof(InjectedObjectModelBinder))]InjectedObject a, ConstructedObject b)

, , . -, , InjectedObject ModelBinder:

[ModelBinder(typeof(InjectedObjectModelBinder))]
public class InjectedObject
{....

, HttpConfiguration Register WebApiConfig:

var provider = new SimpleModelBinderProvider(typeof(InjectedObject), new InjectedObjectModelBinder());
config.Services.Insert(typeof(ModelBinderProvider), 0, provider);

ConstructedObject InjectedObject :

[ModelBinder(typeof(InjectedObjectModelBinder))]
public class InjectedObject
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ConstructedObject
{
    public int A { get; set; }
    public int B { get; set; }
    public string C { get; set; }
}

, :

public void Post(InjectedObject a, ConstructedObject b)
{
    //a will be populated in our model binder.
}

, , Fiddler, :

POST http://localhost:64577/api/values HTTP/1.1
Host: localhost:64577
Accept: */*
Content-Type: application/json
Connection: keep-alive
Content-Length: 51
your_key: This came from the header

{"a":1,"b":2,"c":"This was 'normal' model binding"}

, /:

Watch window with correctly bound values

Web API .

+4

All Articles