3

I'm building an API where the client can send me a blob of data and I save it somewhere for retrieval later. I don't care what the content-type is. I just want to get the raw data every time, no matter what they set Content-Type to. I know this can be achieved in older versions of ASPNET by accessing the Request object, but this does not seem possible with ASPNET 5, nor would I want to do this because it would make unit testing impossible (Request is not dependency injected).

I've seen some mentions of the IInputFormatter and IOutputFormatter interfaces, but those seem to attach to a specific Content-Type. I think I'm looking for something that's more like the [FromBody] attribute, but that gives me raw output. Something like [RawBody]. I've done quite a bit of searching and can't seem to find any simple solutions for this.

Kevin Craft
  • 849
  • 8
  • 18
  • Maybe you can use the Request object if you can unit test it with Moq [per this answer](http://stackoverflow.com/a/970272/3585500). – ourmandave Jan 19 '16 at 01:46
  • I don't think this would work with ASPNET 5 since the controller doesn't inherit from anything (just object). Hence, there is no ControllerContext or anything. I'm not even sure if its possible to access the Request from the controller in ASPNET 5. I think an attribute similar to [FromBody] may be the only way to do this. – Kevin Craft Jan 19 '16 at 16:43

2 Answers2

0

you can create CustomAttribute and read Request.InputStream with StreamReader Save stream data where ever you want then reset InputStream position to 0 httpContext.Request.InputStream.Position = 0;

I used it in Custom AuthorizeAttribute but you can use use Custom ActionFilter and use Request from filterContext you can google for "Custom Attribute in MVC c#" you can also do that in ActionResult.

  • Thank you. This sounds like it is on the right track to me. Do you think you could provide a template for how this would work? Or perhaps a link to a relevant sample? – Kevin Craft Jan 19 '16 at 20:32
  • This sounds like an MVC 4 (or earlier) concept. I don't think this can be done on MVC 6 (ASPNET 5). It is a completely different architecture. I do think my problem is going to require a custom attribute, though. I've been looking into InputFormatters as well as ModelBinders. I think the solution will have something to do with those. – Kevin Craft Jan 19 '16 at 20:42
  • @KevinCraft MVC or .NET's Architecture may change but HTTP Protocol is still same.. you want to get Raw Request (data blob) from Client's HTTP Request, and you can get it from Request.InputStream, I don't have mvc6 installed but if you can access Request.InputStream anywhere, you can achieve this functionality with that. – Devson Technologies Jan 19 '16 at 21:03
  • I understand what I need to do once I have access to the Request object. That's the problem I'm facing, though. MVC 6 is purposely built to be unit testable. Everything is injected. The controller itself doesn't even have a context or anything. Everything is handled by the Dependency Injector. I need to figure out how to get in between the DI system and the controller. I think I'm on the right track with ModelBinders. – Kevin Craft Jan 19 '16 at 21:09
  • @KevinCraft Sorry, didn't researched bout mvc 6 before answering. :) – Devson Technologies Jan 19 '16 at 21:25
0

If you are still looking for solution to get Request Object here is the solution

Create MessageHandler

public class MessageHandler1 : DelegatingHandler
    {
        protected async override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpContextWrapper context = (HttpContextWrapper)request.Properties.ElementAt(0).Value;
        // Call the inner handler.
        var response = await base.SendAsync(request, cancellationToken);

        return response;
        }
    }

add Entry to WebApiConfig

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            config.MessageHandlers.Add(new MessageHandler1());

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

Now you can access row Request in MessageHandler1