This question already has answers here:
ASP.NET Core v2 (2015) MVC : How to get raw JSON bound to a string without a type?
(10 answers)
Closed 1 year ago.
I have API, that recieve JSON from body, which is send from some WebUI.
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
public IActionResult Create([FromBody] MyModel request)
{
MyModel newRecord = new();
try
{
newRecord.Id = null;
newRecord.Date = request.Date;
newRecord.Name = request.Name;
}
catch (Exception e)
{
return StatusCode(400, $"Error: {e.Message}");
}
return Ok(newRecord);
}
}
But request is not constant. It changes with develepment.
Right know i have to match MyModel with request to work on JSON in Body. But it generates too much work, because of many changes.
Is there a solution, so I can recieve uknown JSON object and parse it inside of controler?
For example, is there a trick, so I can write
public IActionResult Create([FromBody] var request)
or something similiar?
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();
}
I'm trying to send data as plain Json, from my controller to the client side of my MVC application. The data is initially collected as a list of objects but I'm having trouble converting it to straight Json. Right now the code in my controller is as follows:
[HttpGet]
public JsonResult SecurityPermissionsTableData()
{
List<SecurityPermissionsGridModel> list = securityPermissionsTable.Get(System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\').Last());
string json = JsonConvert.SerializeObject(new
{
data = list
});
return ResultJson(json);
}
public JsonResult ResultJson(object data)
{
return new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = data };
}
When I use the JsonConvert.SerializeObject() function, it returns a string:
"{\"data\":[{\"Username\":\"loganfg\",\"readbutton\":null,\"editbutton\":null,\"deletebutton\":null}]}"
However I need to return plain Json in the form of:
{"data":[{"Username":"lgilmore","readbutton":"<a onclick='SP_read(\"7\")' class='SRKbutton tiny SP_rbutton'>Details</a>","editbutton":null,"deletebutton":null}]}
How can I convert the string the serialize function returns to plain Json? Or how do I alter my ResultJson() function to properly handle and convert the string?
JsonResult already serializes the object for you.
Therefore, it's serializing your string to a JSON string literal.
You should get rid of all of your code and just
return Json(list, JsonRequestBehaviour.AllowGet);
You may simply use the Json method.
Pass the object you want to convert to json as the parameter.
public JsonResult SecurityPermissionsTableData()
{
var permissionList = securityPermissionsTable
.Get(System.Security.Principal.WindowsIdentity.GetCurrent()
.Name.Split('\\').Last());
return Json(permissionList , JsonRequestBehaviour.AllowGet);
}
I have a method that originally returned an HttpResponseMessage and I'd like to convert this to return IHttpActionResult.
My problem is the current code is using JSON.Net to serialize a complex generic tree structure, which it does well using a custom JsonConverter I wrote (the code is working fine).
Here's what it returns:
string json = NodeToJson(personNode);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
The NodeToJson method is where the custom converter comes into play ...
private static string NodeToJson(Node<Person> personNode) {
var settings = new JsonSerializerSettings {
Converters = new List<JsonConverter> { new OrgChartConverter() },
Formatting = Formatting.Indented
};
return JsonConvert.SerializeObject(personNode, settings);
}
Note this returns a string, formatted as JSON.
If I switch this to IHttpActionResult, it seems to fail regardless of what I try. I can just leave it (it works) but I am supposed to be using best practices for this and IHttpActionResult seems to be what I should be using.
I have tried to return Json(json); but this results in invalid, unparsable JSON, presumably because it's trying to do a double conversion?
return Ok(json); results in the JSON string being wrapped in XML.
What is the right way to do this?
EDIT:
I have successfully converted every method in this project to use IHttpActionResult now except this particular method.
It's a serialization of a generic tree to JSON. Regardless of what approach I try, I get back invalid JSON. The HttpResponseMsessage approach works fine, but I can not get valid JSON back with IHttpActionResult.
You can create your own IHttpActionResult class instance to return the JSON and a method in your controller or base controller class to utilize it.
Create the IHttpActionResult instance that sets the content and status code:
public class JsonTextActionResult : IHttpActionResult
{
public HttpRequestMessage Request { get; }
public string JsonText { get; }
public JsonTextActionResult(HttpRequestMessage request, string jsonText)
{
Request = request;
JsonText = jsonText;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
public HttpResponseMessage Execute()
{
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(JsonText, Encoding.UTF8, "application/json");
return response;
}
}
Add a method to your controller to create the result. Here is a Web API example:
public class MyApiController : ApiController
{
protected internal virtual JsonTextActionResult JsonText(string jsonText)
{
return new JsonTextActionResult(Request, jsonText);
}
[HttpGet]
public IHttpActionResult GetJson()
{
string json = GetSomeJsonText();
return JsonText(json);
}
}
Another recommendation is as below;
var json = JToken.FromObject(yourObject);
return Ok(json);
I've got the same problem and this piece of code worked for me (Using Newtonsoft.Json nuget package to deserialize the json):
var unserializedContent = JsonConvert.DeserializeObject(json);
return Json(unserializedContent);
It seems we must have an object in order to Json() work as it should.
Some of the solutions here are converting string to JSON, that's not necessary.
You are just using computer resources for nothing.
// Instead of
// return Ok(jsonstring);
// do:
HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonstring, Encoding.UTF8, "application/json");
Request.RegisterForDispose(response); //To avoid the Pragma CA2000 warning
return ResponseMessage(response);
Another solution At client side
You can make a small change to be prepared to receive a string and convert it if necessary. The code bellow is Javascript
var data;
if (typeof weapiresponse == "string")
data = JSON.parse(weapiresponse);
else
data = weapiresponse;
If you have no intention of using XML as a return type, you can also remove the XmlFormatter in your WebApiConfig:
config.Formatters.Remove(config.Formatters.XmlFormatter);
The correct way is to return:
Ok(json);
It's converting the result to XML because that's the default accepted return type. Try adding:
Accept: application/json into your API request headers, I think that should resolve the issue.
I had the same problem with web-service returning JSON string in a XML-tag. I tried all the simple solutions Like :
return Json(text) , json deserialize and adding config.Formatter for json, but that did't help. I got double cotes around the json object or it was malformed.
Only the solution written by TGRA worked for me.
create your own IHttpActionResult class instance to return the JSON
For me, the only way to return an IHttpActionResult with the string content as Json in the following.
[HttpGet]
public IHttpActionResult ReturnStringAsJson()
{
return this.ResponseMessage(new HttpResponseMessage
{
Content = new StringContent("[json string]"),
Encoding.UTF8,
"application/json"),
});
}
Option 1:
If I deserialize my JSON request manually, I get a correct result:
[Route("search")]
[HttpPost]
public IEnumerable<ErrorLogDto> Search(HttpRequestMessage request)
{
string res = request.Content.ReadAsStringAsync().Result;
LogSearchDto dto = JsonConvert.DeserializeObject(res, typeof(LogSearchDto)) as LogSearchDto;
//dto = not null
Option 2: If I use this, I always get NULL value for dto:
[Route("search")]
[HttpPost]
public IEnumerable<ErrorLogDto> Search([FromBody]LogSearchDto dto)
{
// dto = null!
I am out of ideas how to debug this..
After a long search, I solved the problem by removing following lines from Global.asax.cs:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = true;
In my MVC3 application I need to return an XML representation of a class that has DataContract attribute on it. MVC3 actions return ActionResults.
[HttpGet]
ActionResult MyActionResult( paramsHere )
{
if(!ValidateParams(paramsHere)) {
return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
var myDataContractAttributedObject = getObject();
return ... // how do I convert my [DataContract]-attributed object to ActionResult?
}
I guess I can use DataContractSerializer explicitly but isn't there maybe some automatic MVC magic for doing this?
How do I get ActionResult from my [DataContract]-attributed object?