How to deserialize string that get from Stream using c#? - c#

I have an API which handles call back event of HelloSign. I get Stream in the request data. I convert that Stream into String using following code and it provide me following string.
public bool HSEventCallback(Stream stream)
{
bool callbackStatus = false;
try
{
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
callbackStatus = true;
}
catch (Exception ex)
{
callbackStatus = false;
}
return callbackStatus;
}
Result
------------------------------5sdf54df6a5s4df6 Content-Disposition: form-data; name="json"
{"event":{"event_type":"callback_test","event_time":"514651651","event_hash":"65a65adsxv34adsv514dv6514v6s584v6a5v46a5sv46sd5v146v54s6av4s6av54ds6v46av","event_metadata":{"related_signature_id":null,"reported_for_account_id":"564as4df65a4f65sd4f65sad4f6sad5f46sdf54s6df54","reported_for_app_id":null,"event_message":null}}}
------------------------------5sdf54df6a5s4df6--
Can anybody please suggest me how to de serialize above string. I can deserialize by replacing some of text and by creating class of `event'. But I don't know whether it will work for all kind of data.
Please suggest standard way to deserialize above string.

Related

How to check if json from url is equal to downloaded version C#

I have a json that is read locally and is used in my program. Now I want the local json to be checked with the json from the api url and if it is not equal to the local json file it will be downloaded. Only the biggest problem is that it doesn't execute the code of the two if statements in the check! What is wrong with my code for this check?
This is what I tried to use
public static rootObject LoadJsonLocal()
{
rootObject rootObject = new rootObject();
var path = pathToJson();
string file;
using (StreamReader r = new StreamReader(path))
{
file = r.ReadToEnd();
rootObject = JsonSerializer.Deserialize<rootObject>(file);
}
return rootObject;
}
public static string pathToJson()
{
string extractPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string path = extractPath + "/" + "getlatest.json";
return path;
}
public static async Task UpdateOrDownloadJson()
{
try
{
string str = "url";
WebClient webClient = new WebClient();
webClient.Headers.Add("Authorization", await Header.getAuthorizationHeader());
string JsonSting = webClient.DownloadString(str);
if (JsonSting.Equals(LoadJsonLocal()))
{
Console.WriteLine("Json is equal");
}
// json is not equal download it
if (!JsonSting.Equals(LoadJsonLocal()))
{
await Downloader.DownloadJson();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
You are comparing the downloaded json string to the already present local json deserialized to object form, they are not going to get compared correctly. You should override the Equals() method for your JSON model object[you named it rootObject] so that the comparison can be proper - between local json deserialized into object form and downloaded string deserialized into object form.
To use Equals() or to implement custom equality comparer refer this SO answer

Deserialize Json String to Object

I'm trying to get weather data from online as json and then deserialize the json into an object that I can use. Here's my code:
public static RootObject7 GetWeather7(int zip)
{
var url = "http://api.weatherunlocked.com/api/forecast/us." + zip.ToString() + "?app_id=xxxxxxx&app_key=xxxxxxxxxxxxxxxxxxxxxxx";
var weather = new wunlocked();
string json = weather.getJson(url);
JavaScriptSerializer serializer = new JavaScriptSerializer();
var data = (RootObject7)serializer.Deserialize<RootObject7>(json);
return data;
}
private string getJson(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
}
throw;
}
}
I'm debugging, and what's happening is my RootObject7 data object is being created, and inside it has a "Forecast" object, which is supposed to contain a list of other information but instead it's null. I've already defined all of the classes (they're long, so if it's important, I'll post them but otherwise I don't think I need to). I've never done anything like this before so most of this came from other code examples on here that I've found, but obviously I didn't put them together correctly, since my object is always null but when I go to the url, there's valid xml there. I'm not sure if I need to be somehow converting the xml to json in my code, or if that is being done somehow? Like I said, I really don't know what I'm doing but if anyone has suggestions, that'd be great.
Try
dynamic data = serializer.Deserialize(json);
and then inspect the data object in the debugger - you may not need to deserialise to a fixed interface to get out the data you need. Using dynamic may also be a more robust solution to deal with upgrades to the service that may make a set interface/object more brittle.

Access the RAW XML data in Web API

I am using Web API to receive XML data and convert it to an Object. Which is working fine.
public void Post([FromBody] trackermessages model)
{
try
{
How do I get the RAW XML data? Is there a way to get the XML data as the Request begins or inside this action?
I tried this:
public void Post([FromBody] trackermessages model, [FromBody] string rawText)
{
try
{
But this is not allowed.
I also tried this:
public void Post([FromBody] trackermessages model)
{
try
{
var strean = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
But I get the Exception:
This method or property is not supported after
HttpRequest.GetBufferlessInputStream has been invoked.
EDIT:
I am getting the Exception:
var stream = await Request.Content.ReadAsStreamAsync();
stream.Seek(0, System.IO.SeekOrigin.Begin); // On this Line
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
This is how I did it, because I had to read the RAW data then convert to Object:
public void Post(HttpRequestMessage request)
{
// Reading data as XML string to log to files - In case message structure is changed
var xmlDoc = new XmlDocument();
xmlDoc.Load(request.Content.ReadAsStreamAsync().Result);
var str = xmlDoc.InnerXml;
// Convert to model
var model = XMLHelper.FromXml<trackermessages>(str);
}
And the XMLHelper was copied from another question on stackoverflow: https://stackoverflow.com/a/3187539/1910735
Yes, you can get the raw XML. You do need to seek back to the start of the stream since it will have been read to the end when processing the Model.
public async void Post([FromBody]TestModel value)
{
var stream = await this.Request.Content.ReadAsStreamAsync();
stream.Seek(0, System.IO.SeekOrigin.Begin);
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
Console.Write(text);
}
The problem then is that your application is using GetBufferlessInputStream to read uploads without buffering them. While that is good for memory usage on the server, it means that after you've read the stream once it will no longer be available.
Your stream is being read like this when populating your model. By default GetBufferedInputStream is used which is why it works for me.
I suggest that you take the raw XML as input into the action and then manually deserialize into the model. Alternatively you can switch back to accepting posted data into a buffer.
You probably followed something like this to turn it on : https://blogs.msdn.microsoft.com/kiranchalla/2012/09/04/receiving-request-file-or-data-in-streamed-mode-at-a-web-api-service/ and should undo that to turn it off.

C# WebClient StreamReader string replace not working

I want to read the response from the URI and modify it by replacing all S's to X's and to return that string back to client.
Below is my code, but replace is not working.
I downloaded the "response" string to check and there are lots of S characters.
Any idea why this is not working or how can I manipulate this ?
try
{
// open and read from the supplied URI
stream = webClient.OpenRead(uri);
reader = new StreamReader(stream);
response = reader.ReadToEnd();
response.Replace('S', 'X');
webClient.DownloadFile(uri, "C://Users//MyPC//Desktop//a.txt");
}
Thanks..
you can use webClient.DownloadString(uri)
like this:
string str = webClient.DownloadString(uri).Replace('S', 'X');
File.WriteAllText(#"C://Users//MyPC//Desktop//a.txt", str);

WCF - Stream parameter is missing CR of CRLF

The problem I have is that the client is sending me a string of data as a stream. WCF then normalizes (removes the CR part of CRLF) and I get a hash mismatch between server and client on that specific string.
public void SomeWcfContract(Stream input)
{
try
{
string processed = ReadStream(input);
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
}
catch (Exception ex)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
}
}
private string ReadStream(Stream input)
{
string output;
using (var reader = new StreamReader(input, Encoding.UTF8))
{
output = reader.ReadToEnd();
}
return output;
}
I read a post about this here : XML deserialization 'standardising' line endings, how to stop it? (.NET)
It's the exact same problem I have but I use the standard XmlSerializer of WCF. Do I need to create my own XmlSerializer implementation or can I add the "fix" to the settings somehow?
This seems to be a VERY nasty bug with the WCF XmlDictionaryReader what happens is that when WCF serializes the incoming stream to a Message all instances of carriage return in (CRLF) is removed and replaced with LF. According to this it's a known bug in WCF.
EDIT I reported this as a bug to Microsoft : https://connect.microsoft.com/wcf/feedback/details/532196/xmldictionaryreader-is-normalizing-incoming-stream-removing-cr-of-crlf#details
This seems to fix that problem:
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = UriTemplates.SomeWcfContract), OperationContract]
void SomeWcfContract(Stream vcard);
I guess it makes sense since this would cause the parameter not to be wrapped or something like that.

Categories