C#/.NET: XDocument always has the wrong encoding - c#

I've got a problem with the XDocument class. I am loading information of online XML API, for my first WP8.1 App, like this:
try
{
var xmlDoc = XDocument.Load(_url);
return xmlDoc;
}
catch (XmlException)
{
HttpClient http = new HttpClient();
HttpResponseMessage response = await http.GetAsync(new Uri(_url));
var webresponse = await response.Content.ReadAsStringAsync();
var content = XmlCharacterWhitelist(webresponse);
var xmlDoc = XDocument.Parse(content);
return xmlDoc;
}
But both ways are returning the wrong encoding. For example German umlauts are shown the wrong way. Every XML file I load has
xml version="1.0" encoding="utf-8"
in the top line. Any ideas?

Rather than read the data into a byte array and decoding it yourself, just read it as a stream and let XDocument.Load detect the encoding from the data:
using (HttpClient http = new HttpClient())
{
using (var response = await http.GetAsync(new Uri(_url)))
{
using (var stream = await response.Content.ReadAsStreamAsync())
{
return XDocument.Load(stream);
}
}
}

I fixed it by doing this:
HttpClient http = new HttpClient();
var response = await http.GetAsync(new Uri(_url));
var buffer = await response.Content.ReadAsBufferAsync();
byte[] byteArray = buffer.ToArray();
string content = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
var xmlDoc = XDocument.Parse(content);
return xmlDoc;

Using an XmlReader should resolve issue
string content = "your xml here";
StringReader sReader = new StringReader(content);
XmlTextReader xReader = new XmlTextReader(sReader);
XDocument xmlDoc = (XDocument)XDocument.ReadFrom(xReader);

Related

Using C# HttpClient to POST File without multipart/form-data

I'm trying to interact with a API that doesn't support multipart/form-data for uploading a file.
I've been able to get this to work with the older WebClient but since it's being deprecated I wanted to utilize the newer HttpClient.
The code I have for WebClient that works with this end point looks like this:
using (WebClient client = new WebClient())
{
byte[] file = File.ReadAllBytes(filePath);
client.Headers.Add("Authorization", apiKey);
client.Headers.Add("Content-Type", "application/pdf");
byte[] rawResponse = client.UploadData(uploadURI.ToString(), file);
string response = System.Text.Encoding.ASCII.GetString(rawResponse);
JsonDocument doc = JsonDocument.Parse(response);
return doc.RootElement.GetProperty("documentId").ToString();
}
I've not found a way to get an equivalent upload to work with HttpClient since it seems to always use multipart.
I think it would look something like this
using var client = new HttpClient();
var file = File.ReadAllBytes(filePath);
var content = new ByteArrayContent(file);
content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
var result = await client.PostAsync(uploadURI.ToString(), content);
result.EnsureSuccessStatusCode();
var response = await result.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(response);
return doc.RootElement.GetProperty("documentId").ToString();
What speaks against using simply HttpClient's PostAsync method in conjunction with ByteArrayContent?
byte[] fileData = ...;
var payload = new ByteArrayContent(fileData);
payload.Headers.Add("Content-Type", "application/pdf");
myHttpClient.PostAsync(uploadURI, payload);

Not receiving JSON data from Microsoft FaceAPI

I am trying to get JSON data from a picture using Microsoft's FaceAPI. I am receiving a StatusCode OK, but am not getting anything significant back. I have verified that the MemoryStream has the right data (which I am getting from an Image control) by saving it to a file.
private async Task<string> GetJSON()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "mykey");
// Request parameters
queryString["returnFaceId"] = "true";
queryString["returnFaceLandmarks"] = "false";
var uri = "https://api.projectoxford.ai/face/v1.0/detect?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = ImageToByte();
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uri, content);
}
return "";
}
private byte[] ImageToByte()
{
using (MemoryStream stream = new MemoryStream())
{
videoBox.Dispatcher.Invoke(delegate
{
var encoder = new PngBitmapEncoder();
var flippedBitmap = new TransformedBitmap();
flippedBitmap.BeginInit();
flippedBitmap.Source = (BitmapSource)videoBox.Source;
var transform = new ScaleTransform(-1, 1);
flippedBitmap.Transform = transform;
flippedBitmap.EndInit();
encoder.Frames.Add(BitmapFrame.Create(flippedBitmap));
encoder.Save(stream);
});
using (FileStream test = new FileStream("snapshot.bmp", FileMode.Create))
{
stream.Position = 0;
stream.CopyTo(test);
}
return stream.ToArray();
}
}
You'll want to call await response.Content.ReadAsStringAsync() to get the JSON.
Alternatively, you can use the Microsoft.ProjectOxford.Face NuGet package which does the plumbing for you, plus provide C# types thereby relieving you the tedium of parsing the JSON.
I am not a c# programmer but after looking at your code, method GetJSON is returning hard coded empty string that might be the cause you are not getting anything back from the server after invoking this method or second reason could be your asynchronous server configuration is not working properly thus its returning blank first and doing actual operation later.

Android app Json

I writing android app and faced problem.
I have API and write it to file.
Code of writing
string url2 = "http://new.murakami.ua/?mkapi=getProducts";
JsonValue json = await FetchAsync(url2);
string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string filename = System.IO.Path.Combine(path, "myfile.txt");
using (var streamWriter = new StreamWriter(filename, true))
{
streamWriter.Write(json.ToString());
streamWriter.Close();
}
ParseAndDisplay1(json);
ParseAndDisplay2(json);
ParseAndDisplay3(json);
ParseAndDisplay4(json);
ParseAndDisplay5(json);
ParseAndDisplay6(json);
ParseAndDisplay7(json);
ParseAndDisplay8(json);
}
private async Task<JsonValue> FetchAsync(string url)
{
// Create an HTTP web request using the URL:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
// Send the request to the server and wait for the response:
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
//dynamic data = JObject.Parse(jsonDoc[15].ToString);
Console.Out.WriteLine("Response: {0}", jsonDoc.ToString());
// Return the JSON document:
return jsonDoc;
}
}
}
I want to read information from it and display.
I tried something like this, but it don't works.
private void ParseAndDisplay1(JsonValue json)
{
TextView productname = FindViewById<TextView> (Resource.Id.posttittle);
TextView price = FindViewById<TextView> (Resource.Id.price);
TextView weight = FindViewById<TextView> (Resource.Id.weight);
productname.Click += delegate {
var intent404 = new Intent (this, typeof(SoupesDetailActivity1));
StartActivity (intent404);
};
string path = System.Environment.GetFolderPath (System.Environment.SpecialFolder.Personal);
string filename = System.IO.Path.Combine (path, "myfile.txt");
using (var streamReader = new StreamReader (filename, true)) {
JsonValue firstitem = json [81];
productname.Text = firstitem ["post_title"];
price.Text = firstitem ["price"] + " грн";
weight.Text = firstitem ["weight"] + "г";
}
}
Can you help me with this problem?
There are many, many different ways to read/write data in .NET. This is just one fairly simple approach
// assuming data is System.Json.JsonValue with your data
// write data to file
File.WriteAllText(path, data.ToString());
// read back data
string rawdata = File.ReadAllText(path);
// parse it into a JsonValue
JsonValue json = JsonValue.Parse(rawdata);
Man you are using Xamarin. But here some tips of how I solve it in Android native code.
I saved the file in the Assets folder;
them saved the fale with .json extension not .txt;
I accessed it using this code:
private static String loadJSONFromAsset(Context context, String fileName) {
String json = null;
try {
InputStream is = context.getAssets().open("contactos/" + fileName + ".json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer);
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
After that I parse the JSON with no problem.
And it works perfectly, I hope it will help you.

StreamContent from HttpResponseMessage into XML

I'm calling an existing get method from a WebApi Controller which has this code (I cannot modify it)
[HttpGet]
public HttpResponseMessage Get()
{
XmlDataDocument xmldoc = new XmlDataDocument();
FileStream fs = new FileStream("d:\\document.xml", FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
string str = xmldoc.DocumentElement.InnerXml;
return new HttpResponseMessage() { Content = new StringContent(str, Encoding.UTF8, "application/xml") };
}
I've been trying to read this information like this
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync("http://localhost/api/info");
HttpContent content = rm.Content;
I get a StreamContent but what I like to do now is to read this content and try to deserialize it into a Xml Document in order to read the nodes.
How can I get this information from the Stream Content of the HttpContent?
string response;
using(var http = new HttpClient())
{
response = await http.GetStringAsync("http://localhost/api/info");
}
var xml = new XmlDataDocument();
xml.LoadXml(response);
You can use GetStringAsync to get a string instead of an HttpContent object. You also missed the await in your GetAsync.
Note: code has not been tested

Getting an XML sent by Webservice(POST method) in C# .NET

I am developing this application where I need to send an XML file to a webservice and read it from the webservice, and applying the business logic from the webservice, it will send an XML as response.
The thing is that I do know how to read the response the webservice sends, but I don't know how to retrieve the XML that the request sends to the webservice, the variable always comes null. If someone could help me out, I'd be really glad.
Request Method:
(...)
using (var client = new HttpClient())
{
var XMLRequest = Util.BuildXML.CreateRequestXML();
string url = string.Format(WEB_API_HOST + "/Application/MyMethod/");
HttpRequestMessage httpRequest = new HttpRequestMessage()
{
RequestUri = new Uri(url, UriKind.Absolute),
Method = HttpMethod.Post,
Content = new StringContent(XMLRequest.ToString(), Encoding.UTF8, "text/xml")
};
var task = client.SendAsync(httpRequest).ContinueWith((taskwithmsg) =>
{
var response = taskwithmsg.Result;
if (response.IsSuccessStatusCode)
{
var xmlResponse = response.Content.ReadAsStringAsync().Result;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlResponse);
var test = doc.SelectSingleNode("RESPONSE/...").InnerText;
}
else
{
var contentTask = response.Content.ReadAsStringAsync().Result;
throw new Exception(contentTask);
}
});
task.Wait();
}
(...)
And the Webservice ( that is supposed to receive the XML and read it)
[AcceptVerbs("GET", "POST")]
public HttpResponseMessage MyMethod(XmlDocument doc)
{
// Any doc.SelectSingleNode() wouldn't work, the doc variable is null.
var response = new StringBuilder();
response.Append("<?xml version=\"1.0\" standalone=\"yes\"?>");
response.Append("<RESPONSE>");
(...)
response.Append("</RESPONSE>");
var xmlResponse = new HttpResponseMessage()
{
Content = new StringContent(response.ToString(), Encoding.UTF8, "text/xml")
};
return xmlResponse;
}
So how do I get to read the xml in the "MyMethod" method?
Thanks a bunch!

Categories