Hey I am having a weird issue I can't figure out. Basically I am trying to make a simple httpClient post request but I keep getting an "Invalid json primitive:." I have checked on https://jsonlint.com/ and it says this is valid json but my application states otherwise. Any info would be greatly appreciated?
string test = "{\"CurrentUser\":null,\"Stacktrace\":\"System.UnhandledExceptionEventArgs\",\"OtherData\":null,\"UserInput\":\"\",\"TimeStamp\":\"2017-10-10T16:48:58.606512-04:00\"}"
HttpContent httpContent = new StringContent(test);
await httpClient.PostAsync("/api/logException", httpContent);
And the client is initialized like:
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(this.serverURL);
httpClient.Timeout = TimeSpan.FromSeconds(400);
Instead of writing the JSON format on your own (which is prone to error), how about you simply create an object and serialize it to JSON. Have c# do the heavy lifting. First create a class like:
public class Model
{
public string CurrentUser { get; set; } = null;
public string Stacktrace { get; set; } = "System.UnhandledExceptionEventArgs";
public string UserInput { get; set; } = String.Empty;
public string OtherData { get; set; } = null;
public string TimeStamp { get; set; } = "2017-10-10T16:48:58.606512-04:00";
}
Then initialize an object of this class and simply use JavaScriptSerializer to serialize it into json:
Model md = new Model();
System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = ser.Serialize(md);
The result will be in json:
{"CurrentUser":null,"Stacktrace":"System.UnhandledExceptionEventArgs","UserInput":"","OtherData":null,"TimeStamp":"2017-10-10T16:48:58.606512-04:00"}
I'm no expert, but since nobody else has responded, perhaps you just need to set the content type to JSON?
HttpContent httpContent = new StringContent(test, Encoding.UTF8, "application/json");
See POSTing JsonObject With HttpClient From Web API
Try to String.Replace("\", string.Empty) to your json. Perhaps this will work.
Hey thanks for the answers. You are all correct and I appreciate the help. The issue was in the end not actually json. Basically this error was propagating and actually appearing twice after I thinking it was handled. So where I thought it was telling me invalid json existed (where it was breaking) was actually it repeating the same error message from further up the code.
Thanks again.
Related
I have created small class
class JsonResponse
{
public string Response { get; set; }
}
Then in my program I send some json data and wait store reply to the following variable
var ResultJSON = Post(uri, values);
while parsing I get
Service Error: Cannot convert object of type 'System.String' to type
'App.someclass+JsonResponse'
using Newtonsoft.Json;
class JsonResponse
{
public string Response { get; set; }
}
class Utility
{
public JsonResponse JsonDeserialisation(string response)
{
TextReader textReader = new StreamReader(response);
JsonTextReader jsonReader = new JsonTextReader(textReader);
return JsonSerializer.CreateDefault().Deserialize<JsonResponse>(jsonReader);
}
}
class Main
{
static void Program()
{
var ResultJSON = "Json String received from post";//Post(uri, values);
var deserialisedJson = Utility.JsonDeserialisation(ResultJSON);
}
}
Add newtonSoft.json nuget package to project
try
var Result = new JavaScriptSerializer().Deserialize<JsonResponse>(ResultJSON.**Response**);
looks to me that you are trying to deserialize from an object rather than the string response
Try this, may give your JSON file to result variable.
var result = Convert.ToString(ResultJSON);
Try using using newtonsoft.json downloadable here or use the nuget package.
It has a function that does exactly what you want. Expecting the result of the Post is in string format of course.
var result = JsonConvert.DeserializeObject<JsonResponse>(ResultJSON);
Your JsonResponse class must look exacly the same as the json your getting. So make sure if you get more data in the json that you want to save in the class the names are the same.
If you have anymore questions feel free to ask.
Good morning! I'm still learning my way around REST API calls and generally processing HTTP requests, so please provide any feedback :)
I'm trying to make a GET call to a web service, which should return a JSON string that's a set of information, which is supposed to be a SQL record returned in a sort of dictionary-like manner.
However, I am having several hiccups and don't know if I'm approach the resolution correctly:
Call web service. Define it as a 'GET' call.
Process the response and read it using a StreamReader.
Using the NewtonSoft JSON method, deserialize the response into a dictionary format. <-- Currently stuck here.
Use dictionary to my liking.
// Call the Web Service
string url = "{URL HERE}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
request.ContentLength = 0;
//Dictionary<string, string> dataList = null;
try
{
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var json = reader.ReadToEnd();
//Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
var data = JsonConvert.DeserializeObject<List<KeyValuePair<string, List<KeyValuePair<string, string>>>>>(json);
var dataDictionary = data.ToDictionary(
x => x.Key,
x => x.Value.ToDictionary(y => y.Key, y => y.Value));
//dataList = (Dictionary<string, string>) dataDictionary;
var test = dataDictionary["Key"];
What the JSON string from the call sort of looks like:
"[{\"Number\":4,\"FieldABC\":\"ABC\"}]"
Other solutions I have tried:
Using the data type Dictionary instead.
Various other method calls, like the ones commented out in the code.
Another SO post suggested the ToDictionary() call.
Errors I have run into:
{"Value cannot be null.\r\nParameter name: source"} System.Exception {System.ArgumentNullException}
Cannot convert JSON string to JSON object.
Am I misunderstanding how to process the response from the HTTP request? Or am I confusing / misusing data types? Any help is greatly appreciated!
Update: With all the answers below, the solution ended up being a combination of all of the comments! First, I used json2csharp.com to create the object. Then, using the updated HTTP calls recommended below, I deserialized the JSON into a type Lists so that I got a list of length 1 that I could access my information from. Thanks everyone!
So when I use http://json2csharp.com/ for example to use your JSON, I would get:
public class ClassName
{
public int Number { get; set; }
public string FieldABC { get; set; }
}
Use HttpClient, that makes it easier:
using (var client = new HttpClient())
{
var response = await client.GetAsync(progressUrl);
var yourObject == JsonConvert.DeserializeObject<ClassName>(await response .Content.ReadAsStringAsync());
}
Continue with the rest...
You can also use HttpClientExtensions Class.
Cheers!
First make a POCO which exactly matches the response string. Something like this:
public class MyResponseObject {
public int Number { get; set; }
public string FieldABC { get; set; }
// other properties here
}
Assuming you are sent an array of these objects as [{\"Number\":4,\"FieldABC\":\"ABC\"}] suggests then you can deserialize it using
JsonConvert.DeserializeObject<List<MyResponseObject>>(json);
If it is a more complicated object then you can include additional nested objects in your principal object:
public class MyNestedObject {
public string NestedName { get; set; }
public bool IsEnabled { get; set; }
}
public class MyResponseObject {
public List<MyNestedObject> NestedObjects { get; set; }
}
Once you have a List<MyResponseObject> you may find you don't need a dictionary at all, or if you do you can take advantage of the many Linq Enumerable methods without worrying about JSON.
Use HttpClient instead of HttpWebRequest, as follows:
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await httpClient.GetAsync(url);
var data = await response.Content.ReadAsStringAsync();
Dictionary<string, string> ValueList = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
}
On my server I tried this test code:
[AllowAnonymous]
[Route("GetX")]
public IQueryable<Phrase> GetX()
{
var phrases = new List<PhraseX>
{
new PhraseX() {Keyword="abc", Translation1="abc1", Translation2="abc2" },
new PhraseX() {Keyword="def", Translation1="def1", Translation2="def2" },
new PhraseX() {Keyword="ghi", Translation1="ghi1", Translation2="ghi2" },
};
return db.Phrases;
}
Here's what I have so far on the client which is a terminal application:
var request = HttpWebRequest.Create("http://www.example.com/api/Phrase/GetX");
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
I am getting the expected data back but now I am not sure how can I get the data that's returned as json back into a list? Any suggestions on how I could do this?
You need to deserialize the JSON to C# objects.
These links will help you:
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
http://www.newtonsoft.com/json/help/html/deserializeobject.htm
This is how you may do it:
string jsonStr = "[{Keyword:\"abc\", Translation1:\"abc1\", Translation2:\"abc2\" },{Keyword:\"def\", Translation1:\"def1\", Translation2:\"def2\" },{Keyword:\"ghi\", Translation1:\"ghi1\", Translation2:\"ghi2\" }]";
JavaScriptSerializer jss = new JavaScriptSerializer();
List<PhraseX> phrases = jss.Deserialize<List<PhraseX>>(jsonStr);
where PhraseX is a class-
public class PhraseX
{
public string Keyword { get; set; }
public string Translation1 { get; set; }
public string Translation2 { get; set; }
}
Note: You will find JavaScriptSerializer class in System.Web.Extensions.dll
You may also use JSON.NET for same.
Hope it helps.
You can deserialize the JSON to C# objects, as stated in the previous answer.
Using Json.NET (Newtonsoft.Json namespace), you can pass your JSON data to the JsonConvert.DeserializeObject<T>(json_data) method, with T being the data type the JSON should be deserialized into and json_data obviously being the JSON data you have received. You can obviously also use the built-in JavaScriptSerializer if you don't want to introduce a third-party dependency to your solution.
Visual Studio gives you a very easy way to create the C# classes for your JSON, have a look at my answers here and here.
I am trying to call a rest api method from c#. Problem is for all content types it passes null to body parameter.I shared my code below.Apart from this code I have tried to write body parameter to request as stream.It didn't work either. I have also tried 'application/x-www-form-urlencoded' as content type.
Calling rest api method from c# sample:
string token = Server.UrlEncode("v0WE/49uN1/voNwVA1Mb0MiMrMHjFunE2KgH3keKlIqei3b77BzTmsk9OIREken1hO9guP3qd4ipCBQeBO4jiQ==");
string url = "http://localhost:2323/api/Applications/StartProcess?token=" + token;
string data = #"{""ProcessParameters"": [{ ""Name"":""flowStarter"",""Value"": ""Waffles"" }],
""Process"": ""RESTAPISUB""}";
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
client.BaseAddress = new System.Uri(url);
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
System.Net.Http.HttpContent content = new StringContent(data, UTF8Encoding.UTF8, "application/json");
HttpResponseMessage messge = client.PostAsync(url, content).Result;
string description = string.Empty;
if (messge.IsSuccessStatusCode)
{
string result = messge.Content.ReadAsStringAsync().Result;
description = result;
}
Rest api Method:
[HttpPost]
[ActionName("StartProcess")]
public int StartProcess([FromUri]string token,[FromBody]WorkflowStartParameters parameters)
{
try
{
LoginInformation info = CasheProcesses.ReadCashe(token);
eBAWSAPI api = Service.GetWSService();
WorkflowProcess proc = api.StartProcess(info.Id, info.Password, info.ImpersonateUserId, info.Language, parameters);
return proc.ProcessId;
}
catch (Exception ex)
{
throw new Exception("An error occured when starting process,exception detail:" + ex);
}
}
WorkflowStartParameters class structure:
public class WorkflowStartParameters
{
public WorkflowParameter[] ProcessParameters;
public string Process { get; set; }
}
public class WorkflowParameter
{
public string Name { get; set; }
public string Value { get; set; }
}
I have searched this problem a lot. It seems as a very common problem. I just found this solution working properly, passing request parameter to rest api method and reading body parameter from there. But it is not a valid solution for me.
If you have any idea,feel free to share.
Thanks,
Zehra
I don´t know if it can solve your problem, but let me try.
I guess you don´t have to utilize Server.UrlEncode in your call, but:
Dim myUri As New Uri(Token)
And I guess you must not encode also your username and password - try pass them as string.
Your problem appear to be here:
public class WorkflowStartParameters
{
public WorkflowParameter[] ProcessParameters; <---- needs get/set
public string Process { get; set; }
}
This needs to be a public property to serialize properly. Currently you have it set up as a public field. Just add { get; set; } and give that a try. I would also look into serializing with Newtonsoft.Json to ensure your object is properly serialized. Trying to do it with escape strings will be messing the more data you are sending.
By the way there can be issues sometimes serializing arrays, I would change that to :
public List<WorkflowParameter> ProcessParameters{get;set;}
Finally I have achieved to send filled out data to server. It was about serialization problem. But it didn't work with json serialization before send data. I have added DataContract attribute to my class and it works properly.
Unfortunately still I couldn't figure out this when I make ajax calls from java script it works without DataContract attribute but if I call it in c# it needs DataContract attribute. If someone share the information about this I would appreciate!
I am sharing new class structure, everything else but this still same:
[Serializable]
[DataContract]
public class WorkflowParameter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Value { get; set; }
}
[Serializable]
[DataContract]
public class WorkflowStartParameters
{
[DataMember]
public WorkflowParameter[] ProcessParameters { get; set; }
[DataMember]
public string Process { get; set; }
}
How do I correctly deserialise the results of this call (you can click to see output):
https://bitpay.com/api/rates
I'm using a POCO object like this:
public class BitpayPrice
{
public string code { get; set; }
public string name { get; set; }
public double rate { get; set; }
}
And I'm calling the API like so:
var client = new RestClient();
client.BaseUrl = "https://bitpay.com";
var request = new RestRequest("/api/rates", Method.GET);
var response = client.Execute<BitpayPrice[]>(request);
Now, I know that the call to execute is wrong, but how do I un-wrongify it? I'd like to get back an array of BitcoinPrice objects.
RestSharp doesn't support deserializing into array, the best you can get is a List<>:
var response = client.Execute<List<BitpayPrice>>(request);
The reason is that types that you can deserialize to are required to have public parameterless constructor (for performance reasons mostly).