dotnet --version
2.2.300
Create a empty folder. In this folder run
dotnet new webapi
Go to Startup.cs
and comment out app.UseHttpsRedirection();
Run:
dotnet run
Wait for the process to start up. Assuming that you are on a newer build of Windows 10 and have curl.exe
that comes out of the box with Windows 10 run:
curl.exe http://localhost:5000/api/values -X POST -H "Content-Type: application/json" -d "{}"
Observe the result:
{"errors":{"":["Unexpected character encountered while parsing value: {. Path '', line 1, position 1."]},"title":"One or more validation errors occurred.","status":400,"traceId":"0HLN4K718DVA4:00000001"}
Trace Id will be different in your case.
Here is some debug output from a similar but different application. The difference is logging configuration, slightly different, but similar POST
payload, slightly different but similar Content-Type
header, different routes, ports.
[14:02:03 DBG 7] Request matched endpoint 'test.Controllers.ValuesController.Post (test)'
[14:02:03 INF 7] Executing endpoint 'test.Controllers.ValuesController.Post (test)'
[14:02:03 INF 7] Route matched with {action = "Post", controller = "Values"}. Executing controller action with signature Void Post(System.String) on controller test.Controllers.ValuesController (test).
[14:02:03 DBG 7] Execution plan of authorization filters (in the following order): ["None"]
[14:02:03 DBG 7] Execution plan of resource filters (in the following order): ["Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter"]
[14:02:03 DBG 7] Execution plan of action filters (in the following order): ["Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000)", "Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter (Order: -2000)"]
[14:02:03 DBG 7] Execution plan of exception filters (in the following order): ["None"]
[14:02:03 DBG 7] Execution plan of result filters (in the following order): ["Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter", "Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter (Order: -2000)"]
[14:02:03 VRB 7] Resource Filter: Before executing OnResourceExecuting on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:03 VRB 7] Resource Filter: After executing OnResourceExecuting on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:03 DBG 7] Attempting to bind parameter 'value' of type 'System.String' ...
[14:02:03 DBG 7] Attempting to bind parameter 'value' of type 'System.String' using the name '' in request data ...
[14:02:03 DBG 7] Rejected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonPatchInputFormatter' for content type 'application/json; charset=utf-8'.
[14:02:03 DBG 7] Selected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter' for content type 'application/json; charset=utf-8'.
[14:02:03 DBG 7] Connection id "0HLN4KB7M6AHT", Request id "0HLN4KB7M6AHT:00000001": started reading request body.
[14:02:03 DBG 7] Connection id "0HLN4KB7M6AHT", Request id "0HLN4KB7M6AHT:00000001": done reading request body.
[14:02:03 DBG 7] JSON input formatter threw an exception.
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path '', line 1, position 1.
at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadAsString()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
[14:02:03 DBG 7] Done attempting to bind parameter 'value' of type 'System.String'.
[14:02:03 DBG 7] Done attempting to bind parameter 'value' of type 'System.String'.
[14:02:03 DBG 7] Attempting to validate the bound parameter 'value' of type 'System.String' ...
[14:02:03 DBG 7] Done attempting to validate the bound parameter 'value' of type 'System.String'.
[14:02:03 VRB 7] Action Filter: Before executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
[14:02:03 VRB 7] Action Filter: After executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
[14:02:03 VRB 7] Action Filter: Before executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter.
[14:02:04 DBG 7] The request has model state errors, returning an error response.
[14:02:04 VRB 7] Action Filter: After executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter.
[14:02:04 DBG 7] Request was short circuited at action filter 'Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter'.
[14:02:04 VRB 7] Action Filter: Before executing OnActionExecuted on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
[14:02:04 VRB 7] Action Filter: After executing OnActionExecuted on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
[14:02:04 VRB 7] Result Filter: Before executing OnResultExecuting on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 VRB 7] Result Filter: After executing OnResultExecuting on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 VRB 7] Result Filter: Before executing OnResultExecuting on filter Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter.
[14:02:04 VRB 7] Result Filter: After executing OnResultExecuting on filter Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter.
[14:02:04 VRB 7] Before executing action result Microsoft.AspNetCore.Mvc.BadRequestObjectResult.
[14:02:04 DBG 7] List of registered output formatters, in the following order: ["Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.StringOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter"]
[14:02:04 DBG 7] No information found on request to perform content negotiation.
[14:02:04 DBG 7] Attempting to select the first output formatter in the output formatters list which supports a content type from the explicitly specified content types '["application/problem+json", "application/problem+xml"]'.
[14:02:04 DBG 7] Selected output formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter' and content type 'application/problem+json' to write the response.
[14:02:04 INF 7] Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'.
[14:02:04 VRB 7] After executing action result Microsoft.AspNetCore.Mvc.BadRequestObjectResult.
[14:02:04 VRB 7] Result Filter: Before executing OnResultExecuted on filter Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter.
[14:02:04 VRB 7] Result Filter: After executing OnResultExecuted on filter Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter.
[14:02:04 VRB 7] Result Filter: Before executing OnResultExecuted on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 VRB 7] Result Filter: After executing OnResultExecuted on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 VRB 7] Resource Filter: Before executing OnResourceExecuted on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 VRB 7] Resource Filter: After executing OnResourceExecuted on filter Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.
[14:02:04 INF 7] Executed action test.Controllers.ValuesController.Post (test) in 453.5132ms
[14:02:04 INF 7] Executed endpoint 'test.Controllers.ValuesController.Post (test)'
[14:02:04 DBG 7] Connection id "0HLN4KB7M6AHT" completed keep alive response.
[14:02:04 INF 7] Request finished in 589.1984ms 400 application/problem+json; charset=utf-8
It appears that the culprit is JsonInputFormatter
which is triggered because of the application/json
content type.
Questions:
- Why is this happening? I would expect it to work, since
{}
is valid json. - If you put a break point in your Visual Studio on the
Post
method it will not be hit. So it does not seem that you even can read the raw value and parse the json yourself. How do I by pass JsonInputFormatter, given that I don't control theContent-Type
header from the request?
To reproduce this you can use your favorite tool, not just curl, it is also reproducible with Postman, Fiddler, and I assume others.