I'm following this link to copy a document from one folder to another in springCM:
https://developers.docusign.com/clm-api/guides/task-api
at this section of the page: Copy Document Tasks - Initiate Copy - Sample Request
The copy is successful and I can verify that there is a new document in the destination folder, but I'm also trying to get back the object that contains the status and the Href.
But I'm getting an exception when try to desalinize the object to my custom one that matches the response.
"Unexpected character encountered while parsing value: \u001f. Path '', line 0, position 0."
This is my code along with my custom object:
// my custom object
public class SCMDocumentCopyResponse
{
public string Status { get; set; }
public string Href { get; set; }
}
// when in initiating the request
var content = JsonConvert.SerializeObject("{\"DocumentsToCopy\":[{\"Href\":\"https://myapi/documents/785252f4ABC\"}],\"DestinationFolder\":{\"Href\":\"https://myapi/folders/f77e277a-\XYZ"}}");
var buffer = Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync(url, byteContent).ConfigureAwait(false);
string result = await response.Content.ReadAsStringAsync();
var final = JsonConvert.DeserializeObject<SCMDocumentCopyResponse>(result);
What am I doing wrong? Can you give me a working code?
Looks like you have html response from your server.
And when you try to deserialize response - you got this exception.
Try to check you response. Is json really there, as you expect.
Also, you should check response status. And try to deserialize only success response.
Related
My goal is to retrieve JSON data from "The virus tracker" API and parse it into a label. This is for my IB personal project so I just started learning c#. Fount this old code and tried fixing it, it worked with basic GET API's but it doesn't work with the one I'm using. (English not my main language)
POSTMAN RESPONSE
{
"results": [
{
"total_cases": 5954607,
"total_recovered": 2622507,
"total_unresolved": 2255875,
"total_deaths": 363208,
"total_new_cases_today": 53700,
"total_new_deaths_today": 1659,
"total_active_cases": 45257,
"total_serious_cases": 2698001,
"total_affected_countries": 213,
"source": {
"url": "https://thevirustracker.com/"
}
}
],
"stat": "ok"
}
C# CODE
//Creating Client connection
RestClient restClient = new RestClient("https://thevirustracker.com/free-api?global=stats");
//Creating request to get data from server
RestRequest restRequest = new RestRequest("total_cases", Method.GET);
// Executing request to server and checking server response to the it
IRestResponse restResponse = restClient.Execute(restRequest);
// Extracting output data from received response
string response = restResponse.Content;
// Parsing JSON content into element-node JObject
var jObject = JObject.Parse(restResponse.Content);
//Extracting Node element using Getvalue method
string cases = jObject.GetValue("total_cases").ToString();
label1.Text = (cases);
ERROR
An unhandled exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.dll
Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
My final goal with this code is that label1 says "5954607"
Remember that I'm really new to this so if you can explain the changes you made to the code ill really appreciate it.
You're not using RestRequest correctly or initialized the RestClient wrongly.
If that url you used in the RestClient is the whole url then you don't need a "resource" in the RestRequest.
Due to that mistake you got an HTML response indicated by the error
Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
The value of restResponse.Content probably starts with <html and that is not valid JSON.
The Json payload is a bit more complex then you coded for. The results object holds an array with an object that has your stat property.
Putting these fixes together gives you this code.
RestClient restClient = new RestClient("https://thevirustracker.com/free-api?global=stats");
//Creating request to get data from server
RestRequest restRequest = new RestRequest(null, DataFormat.Json);
// Executing request to server and checking server response to the it
IRestResponse restResponse = restClient.Execute(restRequest);
// Extracting output data from received response
string response = restResponse.Content;
// Parsing JSON content into element-node JObject
var jObject = JObject.Parse(restResponse.Content);
//Extracting
// the object has a results property
// that is an array with one item (zero-based)
// on index 0 there is an object
// that has a property total_cases
string cases = (string) jObject["results"][0]["total_cases"];
label1.Text = (cases);
HeyGuys
I'm working on a WebApi project that receives requests from clients and redirects these requests to other services that are not open for direct access.
By default, .Net serializes and deserializes the Json request parameters automatically, so I need to re-serialize them before calling the appropriate service. The same problem occurs when receiving the service response. I need to deserialize it before sending the response to the user; otherwise .Net framework will serialize it one more time, resulting in a "Json of Json" response.
I found this answer but it does not seem to work with .NetCore; so I tried to create my own ModelBinder that just reads the Json object and returns it.
class JsonUnformatterBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
return new JsonUnformatterBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
}
}
and
class JsonUnformatterBinder : IModelBinder
{
private readonly IModelBinder _fallbackBinder;
public JsonUnformatterBinder(IModelBinder fallbackBinder)
{
_fallbackBinder = fallbackBinder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
string currMethod = bindingContext.ActionContext.HttpContext.Request.Method;
if ("POST".Equals(currMethod) || "PUT".Equals(currMethod))
{
string strData = new StreamReader(bindingContext.ActionContext.HttpContext.Request.Body).ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(strData);
return Task.CompletedTask;
}
return _fallbackBinder.BindModelAsync(bindingContext);
}
}
This code is very simple, it was my first attempt and it worked well for my purposes. However, I still get the "Json of Json" problem when I take the second service answer and returns back to the user.
I basically have no idea what I can do to overcome this, so any workaround is welcome here.
If you need just redirect a request without modification, you could read it from input stream directly and send it to inner service. You could also use such approach to read responce from inner service.
//1. Set empty parameter list in action then neither serializator nor model binder are not invoked.
public async Task<ContentResult> ProxyAction(/*empty parameter list*/)
{
var newUrl = #"https://stackoverflow.com";
var data = this.Request.Body;
using (var client = new HttpClient())
{
//2. Read request body from input stream.
var reader = new StreamReader(data);
var json = reader.ReadToEnd();
using (var content = new StringContent(json))
{
//3. Set correct content type
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(this.Request.ContentType);
//4. Post request to inner service
var response = await client.PostAsync(newUrl, content);
//5. Read response without deserialization
var innerResponse = await response.Content.ReadAsStringAsync();
var contentType = response.Content.Headers.ContentType.ToString();
var statusCode = response.StatusCode;
//6. Return inner response without serialization
var outerResponse = this.Content(innerResponse, contentType);
outerResponse.StatusCode = (int)statusCode;
return outerResponse;
}
}
}
I have this simple method which suppose to get weather data, when I call it this error occur:
System.Runtime.Serialization.SerializationException was unhandled by user code
HResult=-2146233076
Message=There was an error deserializing the object of type UWpWeather.RootObject. Encountered unexpected character '<'.
public async static Task <RootObject> GetWeather(double lat, double lng) {
var http = new HttpClient();
var response = await http.GetAsync("http://api.openweathermap.org/data/2.5/forecast/daily?q=leeds&type=accurate&mode=xml&units=metric&cnt=3&appid= MY AIP-KEY");
string result = await response.Content.ReadAsStringAsync();
var serializer = new DataContractJsonSerializer(typeof (RootObject));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject) serializer.ReadObject(ms);
return data;
}
The API does not honour any of the HTTP content or Accept headers you pass through on the request, but rather it sets the content-type of the response based on the query string parameter.
Your initial URL:
http://api.openweathermap.org/data/2.5/forecast/daily?q=leeds&type=accurate&mode=xml&units=metric&cnt=3&appid=
MY AIP-KEY"
What it should be:
http://api.openweathermap.org/data/2.5/forecast/daily?q=leeds&type=accurate&mode=json&units=metric&cnt=3&appid=
MY AIP-KEY"
That should allow you to deserialize it into your RootObject correctly.
Caveat: I don't have your root object implementation, so I could only verify up until getting a JSON-formatted response back.
I found the answer, my first mistake was using Xml instead of Json when calling my data. second, when I used this website (json2csharp) to convert Json to series of classes that represent my Json it created it fine except one which created as a list public List<List> list { get; set; }
I simply removed that one and my code now is working just fine. thanks all for your support.
I am developing an website for my company and in there I want to tag skills to specific people. So the programming tags that shows in stackoverflow is a valuable source. SO I want to get the tag db of the stackoverflow.
I found an API for that.
API for the TAGS
So what I am trying to do is read this json string and forloop through the pages to get the tags and save them in a DB.
private static void ReadJson()
{
HttpClient client = new HttpClient();
//DefaultRequestHeader to Json
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Create an instance of HttpResponse & invoke the service asynchronously
HttpResponseMessage response = client.GetAsync("https://api.stackexchange.com/2.2/tags?page=400&pagesize=100&order=desc&sort=popular&site=stackoverflow").Result;
//Http Status code 200
if (response.IsSuccessStatusCode)
{
//Read response content result into string variable
string JSON = response.Content.ReadAsStringAsync().Result;
//Deserialize the string(JSON) object
var jObj = (JObject)JsonConvert.DeserializeObject(JSON);
//access items from anonymous (Json object) type and add to the list
var result = jObj["items"].Select(item => new
{
name = item["name"]
}).ToList();
//output the data || NOTE: **NSERT into database table**
foreach (var item in result)
{
Console.WriteLine(item.name);
}
}
}
So at string JSON = response.Content.ReadAsStringAsync().Result;
method it shows some weired charachters ( triangels and shapes ) because of that process is stopping there.
0\0\0�Z�n�8\f��<�E/S��,-�cYtuI�\f�ߗf\a�g�
What I am doing wrong here?
If there any way to make this happen please contribute your answer.
Thanks.
What you're getting is a compressed response. So instead of reading it as a string, read it as a byte[], decompress it and you'll find your JSON string.
static async void DoStuff()
{
HttpClient client = new HttpClient();
var bytes = await client.GetByteArrayAsync("https://api.stackexchange.com/2.2/tags?page=400&pagesize=100&order=desc&sort=popular&site=stackoverflow");
var decompressedJson = new StreamReader(new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress)).ReadToEnd();
// decompressedJson will now contain '{"items":[{"has_synonyms":false, .....'
// Continue with deserialization of JSON
}
static void Main(string[] args)
{
Task t = new Task(DoStuff);
t.Start();
Console.WriteLine("Doing stuff");
Console.ReadLine();
}
}
You can continue with the deserialization from there. Keep in mind that the API will throw an error when you're sending too many requests.
I have a simple class:
public class site
{
public string URL { get; set; }
}
That exists within a http handler. Currently I am posting json to this handler and trying to deserialize it to get the URL out of the string. I am however having a problem with the deserialize part of it.
I have a string "jsonString" that has the json formatted like so:
[{"URL":"http://www.google.com/etc/"}]
Here is my code for the deserialize:
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
string jsonString = String.Empty;
HttpContext.Current.Request.InputStream.Position = 0;
using (StreamReader inputStream = new StreamReader(HttpContext.Current.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
site currSite = new site();
currSite = jsonSerializer.Deserialize<site>(jsonString);
//set response types
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;
//send response
HttpContext.Current.Response.Write(jsonSerializer.Serialize(currSite.URL));
I am then trying to send a response using currSite.URL however it is failing. What am I missing here? I am reasonably confident it is at the deserialize part because if I send a response of jsonString instead of currSite.URL it will work.
Your json string shows that it's an array, not a single entity. You should deserialize it as so:
var result = jsonSerializer.Deserialize<site[]>(jsonString);
And result[0].Url should contain what you are looking for.
Update
Adding sample code:
string json = #"[{""URL"":""http://www.google.com/etc/""}]";
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<site[]>(json);
Console.WriteLine(result[0].URL);
Prints:
http://www.google.com/etc/
If you're simply trying to send back the URL as the response (just the string) there's no need to serialize the value. Just pass currSite.URL to the Write method.
Otherwise, I'm guessing you should serialize the whole currSite object for the response rather than just the URL. It all depends on what kind of response the caller is expecting (which you haven't specified).