Sending a class object with Stream property using Rest - c#

I can send a simple class object with some properties like this:
[DataContract]
public class DeviceInfo
{
[DataMember]
public string DeviceCode { get; set; }
[DataMember]
public string ClientKey { get; set; }
[DataMember]
[XmlIgnore]
public DateTime Timestamp { get; set; }
[DataMember]
public string Token { get; set; }
}
WindowsForm code:
string baseAddress = "http://some_webservice_url";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseAddress);
request.Method = "POST";
request.ContentType = "application/json";
DeviceInfo customData = new DeviceInfo();
customData.DeviceCode = "123456";
customData.ClientKey = "hfhf8djf89dfk9";
customData.Timestamp = "12-12-2013";
customData.Token = "444sdf54df544r";
byte[] byteArray = Encoding.UTF8.GetBytes(Serialize<DeviceInfo>(customData));
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
MessageBox.Show(Utility.ReadResponse(response));
}
// SERIALIZATION PART
public static string Serialize<T>(T obj)
{
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, obj);
string retVal = Encoding.Default.GetString(ms.ToArray());
ms.Dispose();
return retVal;
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
if (input != null)
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
return ms.ToArray();
}
}
What it does is sending DeviceInfo to the server.
But how could I do this using a class object with Stream property:
public class PhotoData
{
public string ProductId { get; set; }
public string PhotoId { get; set; }
public System.IO.Stream FileData { get; set; }
}
This is what I have done so far and it is throwing an error, saying
Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO'
is not expected. Consider using a DataContractResolver or add any types not known statically to the list of
known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types
passed to DataContractSerializer.
StreamReader sr = new StreamReader(openFileDialog1.FileName);
byte[] fileStream = ReadFully(sr.BaseStream);
PhotoData pd = new PhotoData();
pd.FileData = sr.BaseStream;
pd.ProductId = "121513542454545";
pd.PhotoId = textBox4.Text;
baseAddress = "http://someurl/rest/UploadPhotoStream";
request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress));
request.Method = "POST";
request.ContentType = "application/octet-stream";
byteArray = Encoding.UTF8.GetBytes(Serialize<PhotoData>(pd));
request.ContentLength = byteArray.Length;
Stream dataStream2 = request.GetRequestStream();
dataStream2.Write(byteArray, 0, byteArray.Length);
dataStream2.Close();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
MessageBox.Show(Utility.ReadResponse(response));
}

I recommend using a byte[] instead of a Stream.
public class PhotoData
{
public string ProductId { get; set; }
public string PhotoId { get; set; }
public byte[] FileData { get; set; }
}
Then you can read/write to the FileData using a MemoryStream in the conventional way. I'm not entirely sure what your method is attempting to do, but I think it would end up looking a bit like this:
byte[] fileStream = ReadFully(sr.BaseStream);
PhotoData pd = new PhotoData();
pd.FileData = fileStream;

Related

XmlException: Root element is missing. Stream and XmlSerializer

I am trying to run this app (code from net)but getting error XmlException: Root element is missing. Where am I doing wrong? (I am learning to work with XML requests).
Method:
public static T postXMLData<T>(string xml)
{
Console.WriteLine(xml);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Requests.url);
byte[] bytes;
bytes = System.Text.Encoding.ASCII.GetBytes(xml);
request.ContentType = "text/xml; encoding='utf-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
string responseStr = new
StreamReader(responseStream).ReadToEnd();
Console.WriteLine(responseStr);
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(responseStream); //error here
return t;
}
throw new Exception("что то не так");
}
When I run app:
static void Main(string[] args)
{
var req = postXMLData<Responses.Response>(Requests.checkRequest());
if (req.result==0)
Console.WriteLine("ok");
Console.ReadKey();
}
Requests class:
public static string checkPaymentRequisites(string payId, string service, string account, string amount)
{
string req = authReq + $"<providers> <checkPaymentRequisites> <payment id=\"{payId}\"> <from currency=\"{currency}\" amount=\"{amount}\"/> <to currency=\"{currency}\" service=\"{service}\" amount=\"{amount}\" account=\"{account}\" moneyType=\"{moneyType}\"/> <receipt id=\"{receiptId}\" date=\"{dTime}\"/> </payment> </checkPaymentRequisites> </providers> </request>";
return req;
Responses class:
[XmlRoot(ElementName = "payment")]
public class Payment
{
[XmlAttribute(AttributeName = "date")]
public DateTime date { get; set; }
[XmlAttribute(AttributeName = "fatal")]
public string fatal { get; set; }
[XmlAttribute(AttributeName = "id")]
public string id { get; set; }
[XmlAttribute(AttributeName = "result")]
public int result { get; set; }
[XmlAttribute(AttributeName = "saved")]
public bool saved { get; set; }
[XmlAttribute(AttributeName = "status")]
public int status { get; set; }
[XmlAttribute(AttributeName = "uid")]
public long uid { get; set; }
}
[XmlRoot(ElementName = "checkPaymentRequisites")]
public class checkPaymentRequisites
{
[XmlElement(ElementName ="payment")]
public Payment Payment { get; set; }
[XmlElement(ElementName ="extras")]
public Extras Extras { get; set; }
[XmlAttribute(AttributeName ="result")]
public int result { get; set; }
}
[XmlRoot(ElementName = "providers")]
public class Providers
{
[XmlElement(ElementName = "checkPaymentRequisites")]
public checkPaymentRequisites checkPaymentRequisites { get; set; }
}
[XmlRoot(ElementName ="response")]
public class Response
{
[XmlElement(ElementName ="providers")]
public Providers Providers { get; set; }
[XmlAttribute(AttributeName ="result")]
public int result { get; set; }
//[XmlText]
//public string Text { get; set; }
}
The main goal of the app is to deserialize and to display Response from Request in XML.
This problem "XmlException: Root element is missing" is because you do not create a XML document from the response stream. The right code is as below:
...
string xml = HttpUtility.UrlDecode(responseStream.Substring(responseStream.IndexOf("XML=") + 4));
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
T result = new T();
XmlNode newNode = document.DocumentElement;
result.Name = ((XmlAttribute)newNode.Attributes["Name"]).InnerText;
result.ID = ((XmlNode)newNode.FirstChild).InnerText;
using (TextReader reader = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(reader);
}
return result;
Your issue is that you are trying to read the response twice. The stream can only be read once.
So either you can just deserialize it
using var responseStream = response.GetResponseStream();
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(responseStream);
Or you can first copy it into a string to dump to console, then deserialize from that string.
using var responseStream = response.GetResponseStream();
using var sr = new StreamReader(responseStream)
string responseStr = sr.ReadToEnd();
Console.WriteLine(responseStr);
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(new StringReader(responseStr));
However you have a number of other serious issues in your code:
Use of WebRequest which is deprecated and really old. Use HttpClient instead.
You should use await to better manage responsiveness
You are not disposing the stream, nor many other IDisposable objects.
You should cache the XmlSerializer
You have a mismatch between the encoding you are using and the encod
private static HttpClient _client = new(); // cache the client and serializer
private static XmlSerializer _xmlSerializer = new(typeof(T));
public static async Task<T> postXMLData<T>(string xml)
{
Console.WriteLine(xml);
using var message = new HttpRequestMessage(HttpMethod.Post, Requests.url);
message.Content = new StringContent(xml, Encoding.UTF8, "text/xml; encoding='utf-8'");
using var response = await _client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
var responseStr = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseStr);
var t = (T)_xmlSerializer.Deserialize(responseStream);
return t;
}
static async Task Main(string[] args)
{
var req = await postXMLData<Responses.Response>(Requests.checkRequest());
if (req.result == 0)
Console.WriteLine("ok");
Console.ReadKey();
}
If you want to read it as a stream then use
using var responseStream = await response.Content.ReadAsStreamAsync();
using var sr = new StreamReader(responseStream);
var responseStr = await sr.ReadToEndAsync();

How to parse Json WebApi response containing C# list

hi I have a json response like
{"Status":"Success","Message":"Authentication
successful","Data":{"Key":"sdsdIRs99Iebe6QHmawlBsCks9mqfUt6jKYNQ%2bW","UserId":"ddjjj8-11e6-637af7"}}
how can I parse this to read response.
I am doing this way:
private void POST(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
postData="{\"UserName\": \"abc\"," +"\"Password\": \"mypwd\"}";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/x-www-form-urlencoded";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
length = response.ContentLength;
using (var reader = new StreamReader(response.GetResponseStream()))
{
JavaScriptSerializer js = new JavaScriptSerializer();
var objText = reader.ReadToEnd();
string str= objText;
MyObject myojb = (MyObject)js.Deserialize(objText,typeof(MyObject));
}
}
}
catch (WebException ex)
{
// Log exception and throw as for GET example above
}
}
I am able to read "Status" and "Message" but unable to read "Key" and "UserID" values.
Please help!
You can use Newtonsoft Json instead of JavaScriptSerializer the class structure for your json looks like this
public class Rootobject
{
public string Status { get; set; }
public string Message { get; set; }
public Data Data { get; set; }
}
public class Data
{
public string Key { get; set; }
public string UserId { get; set; }
}
Deserialization could be done easily like
Rootobject ro = JsonConvert.DeserializeObject<Rootobject>(json);
Console.WriteLine(ro.Status + ", " + ro.Message + ", " + ro.Data.Key + ", " + ro.Data.UserId);
Guessing (since we don't know the structure of the MyObject class) how you access your data:
String status = myobj.status;
String message = myobj.message;
Now since the other data properties are in the "data" node of your json, you should be able to access them like this:
String key = myobj.data.key;
String userId = myobj.data.userId;

sending push notification using FCM on android device

I can able to send the push notification on my android application using the console. but using server side code, I get the successfully message send notification but actually notification does not able to receive at device end. Please, tell me what is wrong with my code:
public static string SendPushNotification() {
try {
string applicationID = "AAAA4GkXVHA:....-qRw";
string senderId = "963..28";
string deviceId = "APA91bHLV...IC4s";
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/json";
var data = new {
to = deviceId,
notification = new {
body = "hema",
title = "hem",
//priority = "normal",
//sound = "Enabled"
},
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(data);
Byte[] byteArray = Encoding.UTF8.GetBytes(json);
tRequest.Headers.Add(string.Format("Authorization: key={0}", applicationID));
tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream()) {
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse()) {
using (Stream dataStreamResponse = tResponse.GetResponseStream()) {
using (StreamReader tReader = new StreamReader(dataStreamResponse)) {
String sResponseFromServer = tReader.ReadToEnd();
string str = sResponseFromServer;
return str;
}
}
}
}
}
catch (Exception ex) {
string str = ex.Message;
return str;
}
}
where I got the response in return is as follows :
{"multicast_id":8288766196764532656,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1481612825945796%6ad79a87f9fd7ecd"}]}
Sending the json in right format:
{
"to" : "APA91bHLV__P6Qer8U70j82blZt0VdDgc2zo_4DtAD4_MtE-......",
"notification" : {
"body" : "Success!",
"title" : "Hema",
"icon" : "myicon"
}
}
To check it properly, you can also use the postman:
Even I experienced the same problem. Finish all the steps in connecting the FCM from Client side. If you implement GetMessage() method from client side, only then your device is able to get the Notification from Server side
I wrote a small tutorial for this: https://www.kendar.org/?p=/tutorials/notifications with an Android app and a .Net core Server. To summarize here is the "main" server code
public NotificationResult Send(NotificationModel messageData)
{
var result = "-1";
var webAddr = "https://fcm.googleapis.com/fcm/send";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "key=PROJECTSETTINGS->Cloud Messagings->Server Key");
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string strNJson = JsonConvert.SerializeObject(new NotificationMessage
{
To = "/topics/ServiceNow",
Data = new NotificationData
{
Description = messageData.Description,
IncidentNo = messageData.IncidentNo,
ShortDesc = messageData.ShortDesc
},
Notification = new Notification
{
Title = "ServiceNow: Incident No." + messageData.IncidentNo,
Text = "Notification"
}
});
streamWriter.Write(strNJson);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return new NotificationResult
{
Result = result
};
}
And the classes that wrap the message to FCM (with the Json annotations to correct the mismatch between .Net and Json naming standards)
public class NotificationData
{
public string ShortDesc { get; set; }
public long IncidentNo { get; set; }
public string Description { get; set; }
}
public class Notification
{
public Notification()
{
Sound = "default";
}
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("sound")]
public string Sound { get; set; }
}
public class NotificationMessage
{
[JsonProperty("to")]
public string To { get; set; }
[JsonProperty("data")]
public NotificationData Data { get; set; }
[JsonProperty("notification")]
public Notification Notification { get; set; }
}

c# json json.net parse to class

For some time I have a problem with the code.
Trying to retrieve data from the API using the json but when trying to parse json and send it to the class I receives empty string.
The json data looks like this
{"Wynik":{"Token":"String","DataCzasWaznosci":"\/Date(-62135596800000-0000)\/"}
... and this is my code:
public void post()
{
Autoryzacja_zaloguj a_zaloguj = new Autoryzacja_zaloguj();
string url = a_zaloguj.Link;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(a_zaloguj.Json);
req.Method = "POST";
req.ContentType = "application/json";
req.ContentLength = requestBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
string backstr = sr.ReadToEnd();
dynamic d = JObject.Parse(backstr);
var wynik = d.Wynik;
string token = wynik.Token;
DateTime data = wynik.DataCzasWaznosci;
Wyniki wyniki = new Wyniki();
wyniki.test = token;
sr.Close();
res.Close();
}
public class Wyniki
{
public string test { get; internal set; }
}
You could use Newtosoft nugget package for this kind of parsing
http://www.newtonsoft.com/json
public class Wynik
{
public string Token { get; set; }
public DateTime DataCzasWaznosci { get; set; }
}
/*Deserialization part */
string backstr = sr.ReadToEnd();
Wynikm = JsonConvert.DeserializeObject<Wynik>(backstr);

Upload image to kraken.io API using .Net C#

I'm pretty new to web services. Right now I have problem with using the kraken.io API to resize an uploaded image.
When requesting the response, it always throws an exception.
Any help is appreciated. Thank you very much.
Reference to kraken.io API Docs:
https://kraken.io/docs/upload-url
This is what I have done so far
Trigger:
byte[] data = new byte[fuImage.PostedFile.ContentLength];
fuImage.PostedFile.InputStream.Read(data, 0, fuImage.PostedFile.ContentLength);
objKraken krakenio = new objKraken();
krakenio.wait = true;
krakenio.resize = new objKResize() { width = Base_Controller.DealsWidth, height = Base_Controller.DealsHeight, strategy = "exact" };
Controller_Kraken.UploadFile(data, krakenio);
Controller:
public const string UploadAPIUrl = "https://api.kraken.io/v1/upload";
public static bool UploadFile(byte[] data, objKraken krakenInfo)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(UploadAPIUrl);
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data";
string jsonString = JsonConvert.SerializeObject(krakenInfo);
webRequest.ContentLength = data.Length + jsonString.Length;
using (Stream postStream = webRequest.GetRequestStream())
{ // Send the data.
postStream.Write(data, 0, data.Length);
using (StreamWriter swRequest = new StreamWriter(postStream))
{
swRequest.Write(jsonString);
swRequest.Flush();
}
postStream.Close();
}
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
{
string responseText;
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
responseText = reader.ReadToEnd();
}
if (responseText == "true")
{ return true; }
else
{ return false; }
}
else
{ return false; }
}
}
catch
{ return false; }
}
Object:
public class objKraken
{
public objKAuth auth { get { return new objKAuth(); } }
public objKResize resize { get; set; }
public bool wait { get; set; }
}
public class objKAuth
{
public string api_key { get { return ConfigurationManager.AppSettings["ApiKey"]; } }
public string api_secret { get { return ConfigurationManager.AppSettings["SecretKey"]; } }
}
public class objKResize
{
public int width { get; set; }
public int height { get; set; }
public string strategy { get; set; }
}

Categories