How to send back data from a JSON request - c#

I have an existing WSDL which returns information to remote devices using SOAP. However, I'm writing a new app with Android which doesn't support SOAP so I can't use the existing WSDL and have had to code a new app which looks for a querystring from the Android app and returns the data in a JSON packet. I've coded the module which receives the data okay but I'm unsure how to send the data back in JSON format, does anyone have any examples in VB.Net or C# which shows me how to return the data to the JSON requestor?

You'll be pleased to know .NET makes this really simple, using the DataContractJsonSerializer. Here is some code, pulled from a HTTP Handler. MyDataType is the name of your serializable class.
context.Response.ContentType = "application/json";
MyDataType someObject = new MyDataType();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MyDataType));
using (MemoryStream ms = new MemoryStream())
{
ser.WriteObject(ms, data);
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
string json = sr.ReadToEnd();
Trace("Returning JSON:\n" + json + "\n");
context.Response.Write(json);
}
This is the main blog post I used when I had to do this.

Related

How to send AMF3 object via HttpClient Post Request

I am working on a website which is old and uses AMF packages to send data to server. I need to send some text data to this website and save that data to this website. In other words I want to automate this website.
I found fluorinefx library but it is no longer supported by owner and there is no documentation on the internet about that. I tried to use fluorinefx's serialize class to serialize my dictionary data and send that to server with content-type header application/x-amf. But httpclient doesnt support AMF bytearrays.
When I tried to use fluorinefx's NetConnection class and use netConnection.Connect(url) method, if url starts with http:// there is no problem, but if url starts with https// it gives an URİFormat exception. Since the website I am working on uses https:// I cannot use this Connect method either.
So please help me, how can I prepare a correctly structured AMF object and send this with HttpClient. Or is there any other libraries which I can use for sending AMF packages.(I looked WebOrb and DotAmf too but theese are not working either)
Thanks.
public static object SendAMF(string method, object[] arguments)
{
AMFMessage message = new AMFMessage(3);
message.AddHeader(new AMFHeader("headerKey", false, "headerValue"));
message.AddBody(new AMFBody(method, "/1", arguments));
MemoryStream ms = new MemoryStream();
AMFSerializer serializer = new AMFSerializer(ms);
serializer.WriteMessage(message);
serializer.Flush();
serializer.Dispose();
var request = (HttpWebRequest)WebRequest.Create($"{Endpoint}/Gateway.aspx?method={method}");
byte[] data = Encoding.Default.GetBytes(Encoding.Default.GetString(ms.ToArray()));
request.GetRequestStream().Write(data, 0, data.Length);
try
{
var response = (HttpWebResponse)request.GetResponse();
ms = new MemoryStream();
response.GetResponseStream().CopyTo(ms);
dynamic obj = DecodeAMF(ms.ToArray());
ms.Dispose();
response.Dispose();
return obj;
}
catch(Exception ex)
{
ms.Dispose();
return "ERROR! " + ex.ToString();
}
}
public static dynamic DecodeAMF(byte[] body)
{
MemoryStream memoryStream = new MemoryStream(body);
AMFDeserializer amfdeserializer = new AMFDeserializer(memoryStream);
AMFMessage amfmessage = amfdeserializer.ReadAMFMessage();
dynamic content = amfmessage.Bodies[0].Content;
memoryStream.Dispose();
amfdeserializer.Dispose();
return content;
}
`

Using POST to communicate between controller methods on two separate servers

I'm using C# 6.0, ASP.NET 4.5 MVC 4.
I'm developing an API that is essentially a wrapper for another API that generates PDFs. A separate server will be implementing it directly, and all other applications will send their data to this server for conversion. The underlying PDF conversion software has specific system requirements so this will free us from the limitation of what machines our applications can run on. It's also somewhat brittle so isolating it is desireable.
To accomplish this I've set up two separate MVC applications, one with the conversion implementation, the other as a simple application that generates data to be converted, which implements the API I'm developing. They're set up to exchange data using POST.
The problem I've run into is that the PDF server isn't receiving the data to be converted. It runs, but its parameter only contains null. I set it up so that it will return a PDF containing the error if this happens. It comes through successfully, containing the resulting error message it generated so that part of it is functioning properly.
Here's the code running on the PDF server:
[HttpPost]
public FileResult MakePdf(string html)
{
byte[] pdf = null;
var converter = new HtmlToPdfConverter();
try
{
pdf = converter.GeneratePdf(html);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
var errorHtml = errorTop + new Regex("\\s").Replace(e.Message, " ") + errorBottom;
pdf = converter.GeneratePdf(errorHtml);
}
return File(pdf, "application/pdf");
}
Here's the code that's sending the HTML there to be converted:
public byte[] Fetch() {
var webRequest = (HttpWebRequest)WebRequest.Create("http://localhost:60272/PdfServer/MakePdf");
webRequest.Method = "POST";
var encoder = new UTF8Encoding();
byte[] data = encoder.GetBytes(Resource); // Resource contains valid HTML output by ASP.NET
webRequest.ContentLength = data.Length;
webRequest.ContentType = "text/html";
using (var stream = webRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
}
using (var webResponse = webRequest.GetResponse())
{
using (Stream responseStream = webResponse.GetResponseStream())
{
using (var memoryStream = new MemoryStream())
{
int bufferLength = 1024;
data = new byte[bufferLength];
int responseLength = 0;
do
{
responseLength = responseStream.Read(data, 0, bufferLength);
memoryStream.Write(data, 0, responseLength);
} while (responseLength != 0);
data = memoryStream.ToArray();
}
}
}
return data;
}
I haven't tried sending data to an ASP.NET MVC controller method from a separate application before. The code I wrote here is based on examples I've found of how it's done.
Any ideas about what I'm doing wrong?
Try to form encode it: "application/x-www-form-urlencoded" and name the string-data html. So it would look something like:
var s = "html=" + Resource;
And then send s, instead of sending Resource. And of course set the content type to "application/x-www-form-urlencoded". This should help MVC map the data to the html parameter.
That's the only thing I can think of.
On a side note, I think you also should Close() your stream when you're done, rather than flushing it.
===
A final idea would be to try to change your encoding from text/html to text/plain. I know you're thinking it's HTML, but your method is taking in a string. So to MVC it's expecting a string, not HTML, the fact that it's actually HTML is incidental to the MVC deserializer.

Which kind of commpression do I have to use? Or use StreamContent with JsonTextWriter

I'm developing an ASP.NET Web Api 2.2 application with .NET Framework 4.5, C# and Newtonsoft.Json 6.0.8.
I have this method to post to this web api:
protected bool Post<T>(string completeUri, ref T dataToPost)
{
bool result = false;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_webApiHost);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent content = new StringContent(JsonConvert.SerializeObject(dataToPost), Encoding.UTF8, "application/json");
Task<HttpResponseMessage> response = client.PostAsync(completeUri, content);
[ ... ]
}
return result;
}
When I have a lot of data to send I get an Out of Memory exception here:
HttpContent content = new StringContent(JsonConvert.SerializeObject(dataToPost), Encoding.UTF8, "application/json");
I have read a lot about compression but I don't know which one do I have to use. I don't know if there are more types but I have found two kinds: IIS compression and GZip compression.
Which one do I have to use? If I use GZip compression, do I have to modify my web api client?
UPDATE:
I have this class to serialize but I haven't used it:
public static string Serialize(Models.Aggregations aggregation)
{
if (aggregation == null)
throw new ArgumentNullException("aggregation");
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
writer.WritePropertyName("Code");
writer.WriteValue(aggregation.Code);
if (!string.IsNullOrWhiteSpace(aggregation.Created))
{
writer.WritePropertyName("Created");
writer.WriteValue(aggregation.Created);
}
writer.WriteEndObject();
return sw.ToString();
}
It will solve the problem if I use it? I ask this because #CodeCaster has suggested me to use JsonTextWriter but I don't know how to use it inside my post method.
UPDATE 2
Following #CodeCaster recommendation I'm trying to optimize how I send data to that Web Api and I'm writing my own JSON serializer with this class:
public static string Serialize(Models.Aggregations aggregation)
{
if (aggregation == null)
throw new ArgumentNullException("aggregation");
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
writer.WritePropertyName("Code");
writer.WriteValue(aggregation.Code);
if (!string.IsNullOrWhiteSpace(aggregation.Created))
{
writer.WritePropertyName("Created");
writer.WriteValue(aggregation.Created);
}
writer.WriteEndObject();
return sw.ToString();
}
But #CodeCaster has told me that to make it more efficient I will need to write as a Stream into StreamContent using JsonTextWriter.
But I don't know how to do that because I don't know how to instantiate StreamContent. All the examples that I've seen use a var stream but I don't see how they instantiate that object.
How can I use JsonTextWriter to write into the stream?
The compression you're talking about will not solve your problem.
It will only compress the data at the HTTP level. So in your code, you will still get the same, decompressed string, and the same OutOfMemoryException which occurs during deserialization.
You need to change how you deserialize the JSON. See Incremental JSON Parsing in C#.
Edit: sorry, I read entirely the wrong way around. It's the serialization, not deserialization. Still, same issue. Either the serialization itself, or the instantiation of the StringContent throws this exception. You need to serialize it streaming, and directly stream to the output.
So: use StreamContent, not StringContent, and use JsonTextWriter to write into the stream. This way you don't have to have the entire serialized string in memory.
Given results as the IEnumerable<T> containing your objects, you can use JsonTextWriter to write into the response OutputStream in the following way:
// get the response output stream ..
using (StreamWriter stream = new StreamWriter(HttpContext.Current.Response.OutputStream))
using (JsonTextWriter writer = new JsonTextWriter(stream))
{
// .. and use json.net to write the data as json in the stream
var serializer = new JsonSerializer();
serializer.Serialize(writer, results);
}
If you have your own JsonSerializer you can easily plug it in.
The response content will be compressed and chunked. Fast and neat
Response Headers
Transfer-Encoding: chunked
Content-Type: application/json
Content-Encoding: gzip

How to return '£' in RESTfull web services as stream

I'm developing a RESTfull web services using WCF. In this service I'm returning a XML in Stream format which contains '£'. I get this in symbol in XML but on client side I get the '?' instead of '£'.
public Stream HandleMessageStream()
{
StreamReader reader = new StreamReader(request);
string text = "<price>£ 10.00</price>";
UTF8Encoding encoding = new UTF8Encoding();
MemoryStream ms = new MemoryStream(encoding.GetBytes(text));
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
return ms;
}
I tried with different encoding but didn't find the answer.
Can anyone help me?
have you tried using
Server.HtmlEncode ?
string text = Server.HtmlEncode("<price>£ 10.00</price>");

Find the size of a data which i am sending to webservice

Is there any way to find the size of a data which i am sending to webservice from the client in Csharp dotnet
Here's a way to find the size of your data when it's serialized to XML, which is what happens when you call a standard SOAP webservice:
var data = GetMyData();
var serializer = new XmlSerializer(data.GetType())
using(var stream = new MemoryStream())
{
serializer.Serialize(stream, data);
var sizeOfData = stream.Length;
}

Categories

Resources