JSON.NET MVC 4 WebApi - c#

I am creating Controller to return an object in JSON format.
I want to use Newtonsoft.Json library.
I created two methods:
[HttpGet]
[ActionName("RetrieveTestClassJson")]
public ActionResult RetrieveTestClassJson(int id)
{
TestThing testThing = new TestThing() { Name = "LPL.22.334", Type = TypeTest.Component };
JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Formatting = Formatting.Indented;
jsonNetResult.ContentType = "application/json";
jsonNetResult.ContentEncoding = Encoding.Unicode;
jsonNetResult.Data = testThing;
return jsonNetResult;
}
[HttpGet]
[ActionName("RetrieveTestClassCase2")]
public TestThing RetrieveTestClassCase2(int id)
{
TestThing testThing = new TestThing() { Name = "LPL.22.334", Type = TypeTest.Component };
return testThing;
}
when I call RetrieveTestClassJson from ajax or browser url I get:
{"ContentEncoding":{"isThrowException":false,"bigEndian":false,"byteOrderMark":true,"m_codePage":1200,"dataItem":null,"encoderFallback":{"strDefault":"�","bIsMicrosoftBestFitFallback":false},"decoderFallback":{"strDefault":"�","bIsMicrosoftBestFitFallback":false},"m_isReadOnly":true},"ContentType":"application/json","Data":{"Name":"LPL.22.334"},"SerializerSettings":{"ReferenceLoopHandling":0,"MissingMemberHandling":0,"ObjectCreationHandling":0,"NullValueHandling":0,"DefaultValueHandling":0,"Converters":[{"CamelCaseText":true,"CanRead":true,"CanWrite":true}],"PreserveReferencesHandling":0,"TypeNameHandling":0,"TypeNameAssemblyFormat":0,"ConstructorHandling":0,"ContractResolver":null,"ReferenceResolver":null,"TraceWriter":null,"Binder":null,"Error":null,"Context":{"m_additionalContext":null,"m_state":0},"DateFormatString":"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK","MaxDepth":null,"Formatting":0,"DateFormatHandling":0,"DateTimeZoneHandling":3,"DateParseHandling":1,"FloatFormatHandling":0,"FloatParseHandling":0,"StringEscapeHandling":0,"Culture":"(Default)","CheckAdditionalContent":false},"Formatting":1}
When I call RetrieveTestClassCase2 I get normal JSON format.
I removed xml handler for testing purposes for now:
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
I am puzzled of what is going on.

WebApi already has the Json serializer in the pipeline, http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization, so I think in your method where you are explicitly serializing, the result ends up serialized twice. The second method is what you want unless you remove the json formatter as well.

The reason it's return JSON when you don't do anything, is because MVC has its own build in JSON serialzer. Since this is a
[System.Web.Http.HttpGet]
not
[System.Web.Mvc.HttpGet]
it treats what your sending as data and not as markup. That's why it's returning your object as JSON. It knows that your sending just an object, so it serializes it for you. If you wanted the same functionality in a [System.Web.Mvc.HttpGet], you would return a JsonResult instead of an ActionResult.
var result = new JsonResult();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
result.Data = testThing;

Related

.net core returns empty body json on Get request

Having troubles to return json .net core 6.0 C#
I'm using NewtonSoft json library
Obviously I'm doing something wrong...
using NetMQ;
using NetMQ.Sockets;
using Newtonsoft.Json.Linq;
using System.Text;
static JObject j_tmp = new JObject();
private static async Task<IResult> Command1()
{
j_tmp["test"] = "1234";
j_tmp["number"] = 18;
//return Results.Json(j_tmp ); //Doesn;t work, empty body
//return Results.Json(j_tmp.ToString()); //Doesn't work, adds "\r\n" on each break line
return Results.Content(j_tmp.ToString(Newtonsoft.Json.Formatting.None), "application/json; charset=utf-8"); //WORKS
}
when I return JObject object, it appears empty on receiving (frontend)
side
Maybe you want a way to pass the JObject object from contoller to the view ?
If so, you can refer to below demo.
In controller:
static JObject j_tmp = new JObject();
public IActionResult Index()
{
j_tmp["test"] = "1234";
j_tmp["number"] = 18;
ViewBag.j_tmp= j_tmp;
return View(j_tmp);
}
In the view:
#ViewBag.j_tmp
Result:
use this method
private static async Task<JsonResult> Command1()
{
j_tmp["test"] = "1234";
j_tmp["number"] = 18;
//return Results.Json(j_tmp ); //Doesn;t work, empty body
//return Results.Json(j_tmp.ToString()); //Doesn't work, adds "\r\n" on each break line
return Json(new JsonResult(null, new { test = j_tmp["test"], number = j_tmp["number"] }));
}
Assume you are working on ASP.NET Core project (as your question mentioned a GET request) and you are asking how to return a simple json.
The simplest way is to return an anonymous object in your action method.
In your controller:
[HttpGet]
public IActionResult YourAction()
{
return OK(new { test = "1234", number = 18 });
}
Is that what you need?

IdentityServer4.Models.Client as httppost parameter always null in aspnet core 2.x

I am sending an httpPost parameter "client" of type IdentityServer4.Models.Client via a C# console application to a C# web api and client is always null.
If I send a different object using the same code, the parameter is received just fine. This seems to be a problem specific to Identity Server 4 and I don't know what's going on.
Server code:
[HttpPost]
public JsonResult Post(IdentityServer4.Models.Client client){
return Json(new { result = true });
}
Client code:
private static async Task Register(string clientName){
var controllerName = "BasicClient";
var basicClientApi = string.Format("http://localhost:5100/api/{0}", controllerName);
using (var httpClient = new HttpClient()){
var clientData = new IdentityServer4.Models.Client();
var client = new { client = clientData };
client.client.ClientName = clientName;
var json = JsonConvert.SerializeObject(client);
var content = new StringContent(json, Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(basicClientApi, content);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var rawResponse = await response.Content.ReadAsStringAsync();
JObject o = JObject.Parse(rawResponse);
Console.WriteLine(o.ToString());
}
}
}
EDIT
After applying [FromBody] and unwrapping the object, I am still getting null for client in the receiving Web API. One thing caught my eye on the console application debug screen though.. see the image below:
The actual client variable is null in the console application, yet JsonConvert was able to serialize it into something. What's that about?
You are wrapping your model inside an anonymous object, which will turn its JSON representation into something which has nothing in common with your original Client class.
This:
var clientData = new IdentityServer4.Models.Client();
var client = new { client = clientData };
client.client.ClientName = clientName;
var json = JsonConvert.SerializeObject(client);
Will result in a JSON similar to the following:
{
"client": {
"clientName": "foo",
"anotherProperty": "bar",
// other properties omitted for brevity
}
}
But what you really want is just the Client object:
{
"clientName": "foo",
"anotherProperty": "bar",
// other properties omitted for brevity
}
Do not wrap your clientData, just serialize it directly to follow the model inside your MVC Action Method:
var clientData = new IdentityServer4.Models.Client();
clientData.ClientName = clientName;
var json = JsonConvert.SerializeObject(clientData);
For everything to be working, you have to tell the model binder explicitly where to expect the data.
Use [FromBody] attribute on the model.
[FromBody]: Use the configured formatters to bind data from the request body. The formatter is selected based on content type of the request.
[HttpPost]
public IActionResult Post([FromBody]IdentityServer4.Models.Client client) {
return Json(new { result = true });
}
Reference Model Binding in ASP.NET Core
You're not going to believe this, but ultimately the reason why IdentityServer.Models.Client was null in the Web Api post parameter was because the class is decorated with [DebuggerDisplay("{ClientId}")] and I did not provide a ClientId in my test application, so it was always showing up as null when in fact it actually WAS THERE THE WHOLE TIME. I am glad this issue is behind me, but I am very angry about this "feature".

Is it really necessary to return string instead of dictionaries in Get methods in NancyModule?

I'm using Nancy 1.4.3 for HTTP GET requests handling in .Net 4.5 app. I have to response with JSON object on every request. That's how my Get methods in NancyModule class look like:
Get["/getData"] = param =>
{
var dict = new Dictionary<string, object>
{
["Success"] = true
["Data"] = data; //Object
};
return dict;
};
Also, there is a header adding after Get:
After += ctx => {
ctx.Response.Headers["Access-Control-Allow-Origin"] = "*";
};
This code works fine, but it throws a handled RuntimeBinderException: "Cannot convert System.Collections.Generic.Dictionary<string,object> to Nancy.Response". Nevertheless, it answers with a correct JSON object. Have I to convert my Dictionary to string with JSON stringify method, or everything is fine?

How to pass JSON from Android to MVC controller?

In my latest project I want to have a user type in name and password on an Android phone, save it in JSON-format, and POST it to an ASP.NET MVC server which should return configuration data in a new JSON.
What I have so far:
Android (partial code):
String json = "{\"x\": \"val1\",\"y\":\"val2\"}";
URL url = new URL("http://xxxxx/Home/GetData");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json"); // have tried without this
conn.setRequestProperty("Content-Length", json.getBytes().length + "");
conn.setDoOutput(true);
os = conn.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.close();
conn.connect();
The json string here is just for testing.
MVC:
[HttpPost]
public ActionResult GetData(String request)
{
Debug.WriteLine(request.Length); // not relevant to the question
var data = new { Name = "Test", Age = "39" };
return Json(data);
}
Returns JSON with test data.
The string argument in the MVC controller is probably wrong here. I have tried accepting e.g. byte[], but I always end up with NULL.
Any help with this or suggestions for alternatives is appreciated!
Cheers
If this is what's being posted to the server:
{
"x": "val1",
"y": "val2"
}
Then the method parameters should reflect those key/value pairs. Something like this:
public ActionResult GetData(string x, string y)
This will go through everything you post in the json. Prettu much like #David's but for when you have no clue whats being sendt to the GetData
public ActionResult GetData()
{
foreach (var key in Request.Form.AllKeys)
{
//This will iterate through everything in your post data
var value = Request.Form[key];
}
}

Serializing an EnumerableRowCollection into a JSONResult

I have the following method which is supposed to return a JSONResult so I can use it in an AJAX method with javascript and load autocomplete suggestions for a textbox. I will load this everytime a particular dropdown list changes.
[AcceptVerbs(HttpVerbs.Post), Authorize]
private JsonResult GetSchemaNodeValues(string SchemaNodeId)
{
var query = #"Select ld.""Value""
From ""LookupData"" ld, ""SchemaNode"" sn
Where sn.""LookupTypeId"" = ld.""LookupTypeId""
And sn.""SchemaNodeId"" = '{0}'";
DataSet data = new DataSet();
data = ServiceManager.GenericService.ExecuteQuery(String.Format(query, SchemaNodeId)).Data;
var res = data.Tables[0].AsEnumerable().Select(dr => new
{
Value = dr["Value"].ToString()
});
return JsonConvert.SerializeObject(res);
}
I get the following error under return JsonConvert.SerializeObject(res);
Error 106 Cannot implicitly convert type 'string' to 'System.Web.Mvc.JsonResult'
Is there any way to get past this?
Before this I tried using System.Web.mvc.Controller.Json(res); which returns a JSONResult from an object.
But I couldn't use it because my class is a PageDialog not a Controller so it doesn't have access to Controller's protected internal methods like JSon(). The error I got was that JSon() is inaccessible due to its protection level. The Controller class was locked and I can't make it public or create a workaround so I changed the approach using JsonConvert.SerializeObject(res);
Any suggestions would be extremely welcome.
private dynamic GetSchemaNodeValues(string SchemaNodeId)
{
...
return data.Tables[0].AsEnumerable().Select(dr => new
{
Value = dr["Value"].ToString()
});
}
or
private string GetSchemaNodeValues(string SchemaNodeId)
{
...
var result = data.Tables[0].AsEnumerable().Select(dr => new
{
Value = dr["Value"].ToString()
});
return JsonConvert.SerializeObject(result);
}

Categories

Resources