0

I'm having an issue where I can't get POST content to work as expected in Web API.

Following the tutorials I should be able to have routes in a controller that look like the following (form 1):

[Route("my-post-method")]
public HttpResponseMessage MyPostMethod(MyModel model)
{
  Request.CreateResponse(HttpStatus.OK, model.SomeNumber * 5);
}

But this doesn't work. Instead I have to do the following (form 2):

[Route("my-post-method")]
public HttpResponseMessage MyPostMethod()
{
  var text = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
  var model = JsonConvert.DeserializeObject<MyModel>(text);
  Request.CreateResponse(HttpStatusCode.OK, model.SomeNumber * 5);
}

Now, I think this has something to do with the CORS setup on the project but I'm not sure. If I try to make the request to form 1 via Postman everything works as intended. If I try to make the request to form 1 via the browser and I don't set the Content-Type header I get an unsupported media type error on the POST request (this is what I expect to happen), but if I set the Content-Type header to "application/json" then the Web API returns a 404 response on the OPTIONS preflight request. Additionally adding a [FromBody] attribute to the method argument doesn't do anything.

The Web.config contains:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

and the startup config class has:

public static void Register(HttpConfiguration config)
{
  config.EnableCors();
  config.MapHttpAttributeRoutes();

  var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
  jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
  jsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
  jsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
  jsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());

  config.EnsureInitialized();
}
user1806676
  • 169
  • 1
  • 1
  • 10
  • Shouldn't you add the [FromBody](https://stackoverflow.com/questions/24625303/why-do-we-have-to-specify-frombody-and-fromuri-in-asp-net-web-api) attribute? – Serhii Shushliapin May 22 '17 at 15:19
  • You mentioned *forms* and then talked about *Json*. What are you trying to do? Also show us how you are trying to post this model from the browser. – Federico Dipuma May 22 '17 at 15:37
  • 1
    Also, **never** enable CORS two times in the same application for [this reason](https://stackoverflow.com/a/36968863/3670737). Enable it in Web Api **OR** inside `Web.config`, not both. – Federico Dipuma May 22 '17 at 15:40
  • Decorate Action method with EnableCors attribute and also remove CORS stuff from web.config – Rohit Garg May 23 '17 at 06:20

1 Answers1

0

It looks like you need to decorate your method with the [EnableCors] attribute as documented here

https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Requests from postman do not require CORS like client side browser requests.

  • I used var corsConfig = new EnableCorsAttribute("*", "Content-Type", "GET, POST, PUT, PATCH, DELETE, OPTIONS"); config.EnableCors(corsConfig); in the startup config class and removed the CORS stuff from the web.config. It seemed to be the web.config stuff that was causing the issue. – user1806676 May 26 '17 at 16:44