Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override content headers for MVC POST request

I am fairly new to MVC so I am hoping there is a solution to my problem. I am using third party hardware to communicate with my MVC web API. The hardware sends requests in a JSON format which I can extract perfectly fine. However, I am in the process of changing the parameter of these requests into binding model objects due to conflicts.

E.G.

        Public Function POSTRequest(Action As String, Stamp As String) As HttpResponseMessage
           ...
        End Function

        Public Function POSTRequest(Action As String, OpStamp As String) As HttpResponseMessage
           ...
        End Function

So these two methods share the same calling card so they both cannot exist in the same controller.

Due to this, I have created model binding objects to house these parameters instead. The problem is, once I do this, the web API complains about the request saying the "Content-Type" is not defined. Looking at it, the third-party hardware does not send a content-type up with the request. Looking on the net, I have found that this results in the browser treating it as the content type "application/octet-stream". This cannot then translate this into the binding object defined as the parameter.

We have NO control over the third party hardware so we cannot define the content type for these requests. So, my question is, is there a way to intercept these requests and add a content type to them? Or even another way around this?

like image 883
Weebie Avatar asked Dec 12 '16 09:12

Weebie


1 Answers

I think you can use an ActionFilterAttribute. See documentation: Creating Custom Action Filters.

In your case, you can use the following sample (in C# since my VB skills are outdated). It overrides any request Content-Type header with the application/json value. Please note, that you may have to enhance it in order to support every kind of HttpContent (for example, I don't think this should be used for MultiPart requests).

public class UpdateRequestAttribute: ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        actionContext.Request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        base.OnActionExecuting(actionContext);
    }
}

Then you add this attribute to your controller class, for example:

[UpdateRequest]
public class HomeController : ApiController
{
    //[...]
}

In this case all requests to the Home controller will have their Content-Type overridden.


Alternatively, you can also write a custom HTTP Message Handlers which is called very early in the pipeline and will not be limited to a specific controller. Check the following picture to understand how a Request is processed by the server.

ASP.net Server Side handlers

For example, this message handler will set the request Content-Type to application/json if it is currently empty.

public class CustomMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Content.Headers.ContentType == null)
        {
            request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        }
        return base.SendAsync(request, cancellationToken);
    }
}

Finally, here is how to update WebApiConfig in order to add your message handler to the pipeline:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new CustomMessageHandler());

        // Other configuration not shown... 

    }
}
like image 194
Arnaud Develay Avatar answered Sep 30 '22 18:09

Arnaud Develay