ASP.NET Core MVC : How to get raw JSON bound to a string without a type?
The following works in .net core 1.x, but not in .net core 2.x.
As I commented, the solution is to use [FromBody]dynamic data
as my parameter list, using dynamic
instead of string
, and I will receive a JObject
.
Caution: If your architecture calls for a single WebApi server to be equally fluent in producing XML and JSON, depending on content-type header entries, this kind of direct-JSON-consumption strategy can backfire on you. (Supporting both XML and JSON on the same service is possible with sufficient work, but then you're taking stuff that was further UP the MVC asset pipeline and moving it down into your controller methods, which turns out to be against the spirit of MVC, where models come to you as POCOs already parsed.)
Once you convert to a string inside the method, converting the incoming JObject
(Newtonsoft.JSON in memory data type for JSON) to a string.
Found at other answer here.
Sample code, thanks to Jeson Martajaya:
With dynamic:
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]dynamic value)
{
//...
}
Sample code with JObject:
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]Newtonsoft.Json.Linq.JObject value)
{
//...
}
ASP.NET Core 3.0 [FromBody] string content returns The JSON value could not be converted to System.String.
Not sure this help but I think they made some change in .net core 3.0 Newtonsoft.JSON package so you can try this
Install Microsoft.AspNetCore.Mvc.NewtonsoftJson
package.
In your startup.cs add
services.AddControllers().AddNewtonsoftJson();
Recieving uknown JSON to my API and parsing it
System.Text.Json has an class called JsonElement which can be used to bind any JSON to it.
[HttpPost]
public IActionResult Create([FromBody] JsonElement jsonElement)
{
// Get a property
var aJsonProperty = jsonElement.GetProperty("aJsonPropertyName").GetString();
// Deserialize it to a specific type
var specificType = jsonElement.Deserialize<SpecificType>();
return NoContent();
}
MVC controller : get JSON object from HTTP body?
It seems that if
Content-Type: application/json
and- if POST body isn't tightly bound to controller's input object class
Then MVC doesn't really bind the POST body to any particular class. Nor can you just fetch the POST body as a param of the ActionResult (suggested in another answer). Fair enough. You need to fetch it from the request stream yourself and process it.
[HttpPost]
public ActionResult Index(int? id)
{
Stream req = Request.InputStream;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
InputClass input = null;
try
{
// assuming JSON.net/Newtonsoft library from http://json.codeplex.com/
input = JsonConvert.DeserializeObject<InputClass>(json)
}
catch (Exception ex)
{
// Try and handle malformed POST body
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//do stuff
}
Update:
for Asp.Net Core, you have to add [FromBody]
attrib beside your param name in your controller action for complex JSON data types:
[HttpPost]
public ActionResult JsonAction([FromBody]Customer c)
Also, if you want to access the request body as string to parse it yourself, you shall use Request.Body
instead of Request.InputStream
:
Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
Read raw Request.Body in Asp.Net Core MVC Action with Route Parameters
As I suspected the root cause was MVC inspecting the request body in order to try to bind route parameters. This is how model binding works by default for any routes that are not parameter-less, as per documentation.
The framework however does this only when the request content type is not specified, or when it is form data (multipart or url-encoded I assume).
Changing my request content-type to any thing other than form data (e.g. application/json) I can get the framework to ignore the body unless specifically required (e.g. with a [FromBody] route parameter). This is an acceptable solution for my case since I am only interested accepting JSON payloads with content-type application/json.
Implementation of DisableFormValueModelBindingAttribute in Uploading large files with streaming pointed out by @Tseng seems to be a better approach however, so I will look into using that instead, for complete
Why does this return an escaped string of JSON?
That's a valid string representation of your object. If you do JSON.parse() on that string it works just fine. If you dont want it serialized, then just return the actual object:
[HttpPost]
public IHttpActionResult Post(FormDataCollection formData)
{
return this.Ok(formData);
}
Related Topics
C# List<String> to String with Delimiter
The Type or Namespace Name Does Not Exist in the Namespace 'System.Web.Mvc'
How to Download a File from a Website in C#
Setting the User-Agent Header for a Webclient Request
ASP.NET MVC Ambiguous Action Methods
How to Programmatically Connect a Client to a Wcf Service
How to Detect the Language of a String
Is It Worthwhile to Initialize the Collection Size of a List<T> If It's Size Reasonably Known
An ASP.NET Setting Has Been Detected That Does Not Apply in Integrated Managed Pipeline Mode
Redirect from Action Filter Attribute
Will Code in a Finally Statement Fire If I Return a Value in a Try Block
File I/O with Streams - Best Memory Buffer Size
How to Filter "Include" Entities in Entity Framework
Websocket Server: Onopen Function on the Web Socket Is Never Called
Display Image from Database in Asp MVC
How to Deploy Application with SQL Server Database on Clients