Poor performance when parsing JSON - JsonTextWriter as an alternative? - c#

I'm using the code below to parse a JSON response back from the server. It's a little slow. I'm wanting to know if I should be using the JsonTextWriter as an alternative?
How would I implement this using the JsonTextWriter?
string responseString = string.Empty;
Uri uri = new Uri ("http://localhost/complex-json.json");
HttpWebRequest request = new HttpWebRequest (uri);
request.Method = "GET";
HttpWebResponse response = request.GetResponse () as HttpWebResponse;
using (StreamReader sr = new StreamReader(response.GetResponseStream())) {
responseString = sr.ReadToEnd ();
}
response.Close ();
JObject obj = JObject.Parse (responseString);
JArray a = (JArray)obj["questions"];
IList<question> questions = a.ToObject<IList<question>>();
for (int i = 0; i < a.Count; i++) {
Console.WriteLine(questions[0].answer_count);
}

System.Web.Extensions.dll has a JavaScriptSerializer. I use the following 2 extension methods to serialize and deserialize:
public static T JsonDeserialize<T>(this string json)
{
return new JavaScriptSerializer().Deserialize<T>(json);
}
public static string ToJson<T>(this T item)
{
return new JavaScriptSerializer().Serialize(item);
}
Hope this helps.

Related

C# JSON Post using HttpWebRequest

I am new to JSON and C# and trying to write a code that will perform an http web request POST to get a token. Below is my code but I keep getting 400 bad request. Probably my codes just incorrect and I will appreciate for any helps on this. Below is my codes :
static public string GetAuthorizationToken()
{
string token = string.Empty;
string requestUrl = "some URL";
HttpWebRequest httpWebRequest = WebRequest.Create(requestUrl) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "x-www-form-urlencoded";
Dictionary<string, string> postParameters = new Dictionary<string, string>();
postParameters.Add("grant", "some credentials");
postParameters.Add("id", "1234123411");
postParameters.Add("secret", "1234123411");
postParameters.Add("scope", "abcd");
string postData = "";
foreach (string key in postParameters.Keys)
{
postData += WebUtility.UrlEncode(key) + "="
+ WebUtility.UrlEncode(postParameters[key]) + "&";
}
byte[] data = Encoding.ASCII.GetBytes(postData);
httpWebRequest.ContentLength = data.Length;
Stream requestStream = httpWebRequest.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
TokenResponse tokenResponse = new TokenResponse();
using (HttpWebResponse response = httpWebRequest.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
DataContractJsonSerializer responseSerializer = new DataContractJsonSerializer(typeof(TokenResponse));
Stream responseStream = response.GetResponseStream();
object objResponse = responseSerializer.ReadObject(responseStream);
tokenResponse = objResponse as TokenResponse;
response.Close();
if (tokenResponse != null)
{
return tokenResponse.accessToken;
}
}
return token;
}
Here is a precise and accurate example of a POST request and reading the response(though without serializing the JSON data). Only mistake I see so far in your code is an incorrect ContentType also we can't see what url you are trying to send the server(but odds are that it is incorrect). Hope it helps you advance.
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
namespace SExperiment
{
class MainClass
{
public static void Main(string[] args)
{
try{
string webAddr="http://gurujsonrpc.appspot.com/guru";
var httpWebRequest = WebRequest.CreateHttp(webAddr);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{ \"method\" : \"guru.test\", \"params\" : [ \"Guru\" ], \"id\" : 123 }";
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
//Now you have your response.
//or false depending on information in the response
}
}catch(WebException ex){
Console.WriteLine(ex.Message);
}
}
}
}
You have set requestUrl to "some URL". Please try with a web address that exists, in addition to changing the content type to "application/json".

How to post array to url in C# just like AngularJS $http.post(url, data)

In AngularJs I could easily post data to an url by
$http.post(url, data)
data here is an array something like this :
["test1","test2","test3"]
My question is how can I do the same thing in C#? I want to use HttpWebRequest.
Use ToList on your array and FormUrlEncodedContent for your post request, see below
using System.Net.Http;
data.ToList(); //your data, assuming it is already a well-formed array or data model
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
Actually I found the answer myself.
payload here can be an array :
var request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = action;
JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ContractResolver = new UnderscoreMappingResolver(),
Formatting = Formatting.None,
NullValueHandling = NullValueHandling.Ignore,
Converters =
{
new IsoDateTimeConverter
{
DateTimeStyles = DateTimeStyles.RoundtripKind
},
new StringEnumConverter
{
CamelCaseText = true
}
}
};
var json = JsonConvert.SerializeObject(payload, serializerSettings);
request.ContentLength = json.Length;
Console.Out.Write(request.RequestUri);
using (var stream = request.GetRequestStream())
{
using (var sw = new StreamWriter(stream))
{
sw.Write(json);
}
}
HttpWebResponse response;
try
{
response = request.GetResponse() as HttpWebResponse;
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}

call HttpPost method from Client in C# code

I am new to MVC and C#, so sorry if this question seems too basic.
For a HttpPost Controller like below, how do to call this method directly from a client-side program written in C#, without a browser (NOT from a UI form in a browser with a submit button)? I am using .NET 4 and MVC 4.
I am sure the answer is somehwere on the web, but haven't found one so far. Any help is appreciated!
[HttpPost]
public Boolean PostDataToDB(int n, string s)
{
//validate and write to database
return false;
}
For example with this code in the server side:
[HttpPost]
public Boolean PostDataToDB(int n, string s)
{
//validate and write to database
return false;
}
You can use different approches:
With WebClient:
using (var wb = new WebClient())
{
var data = new NameValueCollection();
data["n"] = "42";
data["s"] = "string value";
var response = wb.UploadValues("http://www.example.org/receiver.aspx", "POST", data);
}
With HttpRequest:
var request = (HttpWebRequest)WebRequest.Create("http://www.example.org/receiver.aspx");
var postData = "n=42&s=string value";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
With HttpClient:
using (var client = new HttpClient())
{
var values = new List<KeyValuePair<string, string>>();
values.Add(new KeyValuePair<string, string>("n", "42"));
values.Add(new KeyValuePair<string, string>("s", "string value"));
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.org/receiver.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
}
With WebRequest
WebRequest request = WebRequest.Create ("http://www.example.org/receiver.aspx");
request.Method = "POST";
string postData = "n=42&s=string value";
byte[] byteArray = Encoding.UTF8.GetBytes (postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream ();
dataStream.Write (byteArray, 0, byteArray.Length);
dataStream.Close ();
//Response
WebResponse response = request.GetResponse ();
Console.WriteLine (((HttpWebResponse)response).StatusDescription);
dataStream = response.GetResponseStream ();
StreamReader reader = new StreamReader (dataStream);
string responseFromServer = reader.ReadToEnd ();
Console.WriteLine (responseFromServer);
reader.Close ();
dataStream.Close ();
response.Close ();
see msdn
You can use
First of all you should return valid resutl:
[HttpPost]
public ActionResult PostDataToDB(int n, string s)
{
//validate and write to database
return Json(false);
}
After it you can use HttpClient class from Web Api client libraries NuGet package:
public async bool CallMethod()
{
var rootUrl = "http:...";
bool result;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_rootUrl);
var response= await client.PostAsJsonAsync(methodUrl, new {n = 10, s = "some string"});
result = await response.Content.ReadAsAsync<bool>();
}
return result;
}
You can also use WebClient class:
[HttpPost]
public Boolean PostDataToDB(int n, string s)
{
//validate and write to database
return false;
}
public async bool CallMethod()
{
var rootUrl = "http:...";
bool result;
using (var client = new WebClient())
{
var col = new NameValueCollection();
col.Add("n", "1");
col.Add("s", "2");
var res = await client.UploadValuesAsync(address, col);
string res = Encoding.UTF8.GetString(res);
result = bool.Parse(res);
}
return result;
}
If you decide to use HttpClient implementation. Do not create and dispose of HttpClient for each call to the API. Instead, re-use a single instance of HttpClient. You can achieve that declaring the instance static or implementing a singleton pattern.
Reference: https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
How to implement singleton (good starting point, read the comments on that post): https://codereview.stackexchange.com/questions/149805/implementation-of-a-singleton-httpclient-with-generic-methods
Hopefully below code will help you
[ActionName("Check")]
public async System.Threading.Tasks.Task<bool> CheckPost(HttpRequestMessage request)
{
string body = await request.Content.ReadAsStringAsync();
return true;
}

How I can pass Json from Win Forms to MVC Controller

I have MVC Controller given below:
public ActionResult ReceiveJson(string json)
{
//--
return Content(json, "application/json");
}
I created Windows Forms Application. In the application I want to pass Json to my MVC Controller.
I use:
string json = new JavaScriptSerializer().Serialize(myObject);
using (var client = new CookieAwareWebClient())
{
var values = new NameValueCollection
{
{ "username", login },
{ "password", haslo },
};
client.UploadValues("http://localhost/xxxxx/Login", values);
string link = "http://localhost/xxx/ReceiveJson";
client.Headers.Add("Content-Type", "application/json");
var response = client.UploadString(new Uri (link), "POST", json);
}
This code doesn't work. In ReceiveJson Controller I received null.
http://s22.postimg.org/9vxu2no9t/json.jpg
Can you tell me how I can pass Json from Win Forms to MVC Controller?
Thanks ;-)
Here is working code example:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost/CONTROLLER_NAME/ReceiveJson");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(myObject);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
// If you need to read response
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
have you checked your json value before send it?
Have you tried to uploadstring without adding extra header? In your action you receave string not an object. Here is a good example.
Looks like you violated some MVC conventions.
First you should post your values in request body not in JSON. It will look like this
using(var content = new MultipartFormDataContent())
{
content.Add(new StringContent(firstPropertyName), "firstValue");
content.Add(new StringContent(secondPropertyName), "secondValue");
client.PostAsync("https://mydomain.com/xxx/ReceiveJson", content);
}
Second you should mark your Action with [HttpPost] attribute
Third you should try to receive your viewModel not a string. It will simplify your code on the server
I believe it will help.
It's a good working version:
public ActionResult NamiaryWyZapis()
{
Stream jsonDane = Request.InputStream;
jsonDane.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(jsonDane).ReadToEnd();
//--
}
ANSWER: Via POST.
You need to serialize your object(on this case Persons) to json and make a post with a method like this one. (Person model must be accessible from both applications)
public async bool SendRequestAsync(string requestUrl, object data)
{
string json = JsonConvert.SerializeObject(obj, Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
try
{
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
if (request != null)
{
request.Accept = "application/json";
request.ContentType = "application/json";
request.Method = "POST";
using (var stream = new StreamWriter(await request.GetRequestStreamAsync()))
{
stream.Write(json);
}
using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse)
{
if (response != null && response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
if (response != null)
{
Stream responseStream = response.GetResponseStream();
//return true or false depending on the ok
return GetResponseModel(responseStream);
}
}
}
}
catch (WebException ex)
{
var response = ex.Response;
Stream respStream = response.GetResponseStream();
//return true or false depending on the ok
return GetResponseModel(respStream);
}
catch (Exception e)
{
return false;
}
return false;
}
The GetResponseModel method returns the model that you want to read from the web if your POST was success. Then in your WinForms you can register that success if you want.
The controller method will look like this one
[HttpPost]
public ActionResult JsonMethod(Person p)
{
if(p != null)
return Json(true);
else return Json(false);
}
The body of your GetResponse could be like this one
public static T GetResponseModel<T>(Stream respStream) where T : class
{
if (respStream != null)
{
var respStreamReader = new StreamReader(respStream);
Task<string> rspObj = respStreamReader.ReadToEndAsync();
rspObj.Wait();
T jsonResponse = JsonConvert.DeserializeObject<T>(rspObj.Result);
return jsonResponse;
}
return default(T);
}

How to Deserialize JSON

I'm working on project in which I'm Posting data from asp.net webform to WCF service. I'm posting data through params and the service respond me back a JSON string. Now I have an issue in deserialize. I read many threads but didn't find any solution. Hope someone can sort out my problem. Thanks in Advance
Response from WCF
{"LoginResult":false}
I just want "false" value.
How I tried:
string URL = "http://localhost:32319/ServiceEmployeeLogin.svc";
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(URL+"/"+emp_username+"/"+emp_password+"/"+emp_type);
wrGETURL.Method = "POST";
wrGETURL.ContentType = #"application/json; charset=utf-8";
HttpWebResponse webresponse = wrGETURL.GetResponse() as HttpWebResponse;
Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
// read response stream from response object
StreamReader loResponseStream = new StreamReader(webresponse.GetResponseStream(), enc);
// read string from stream data
strResult = loResponseStream.ReadToEnd();
var jObj = JObject.Parse(strResult);
var dict = jObj["LoginResult"].Children().Cast<JProperty>();
You could use json.net to do it like this:
public class AuthResponse {
public bool LoginResult { get; set; }
}
var deserializedResponse = JsonConvert.DeserializeObject<AuthResponse>(strResult);
http://james.newtonking.com/json
.Net 4.5 has a JavaScriptSerializer, which should work as well:
public class AuthResponse {
public bool LoginResult { get; set; }
}
System.Web.Script.Serialization.JavaScriptSerializer sr = new System.Web.Script.Serialization.JavaScriptSerializer();
AuthResponse response = sr.Deserialize<AuthResponse>(responseText);
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer%28v=vs.110%29.aspx

Categories