POSTing XML with non-ASCII characters - http

I'm trying to patch RestSharp for it to be able to POST XMLs with non-ASCII characters as POST request body.
Here's how it gets written:
private void WriteRequestBody(HttpWebRequest webRequest) {
if (HasBody) {
webRequest.ContentLength = RequestBody.Length;
var requestStream = webRequest.GetRequestStream();
using (var writer = new StreamWriter(requestStream, Encoding.ASCII)) {
writer.Write(RequestBody);
}
}
}
RequestBody is a string and when server actually tries to parse the request, all non-ASCII characters turn into ???.
Now, I do the following:
var encoding = Encoding.UTF8;
webRequest.ContentLength = encoding.GetByteCount(RequestBody);
var requestStream = webRequest.GetRequestStream();
using (var writer = new StreamWriter(requestStream, encoding)) {
writer.Write(RequestBody);
}
But it throws IOException on Stream.Dispose() saying "Cannot close stream until all bytes are written."
How do I post this XML?

I haven't used RestSharp but looking explanation my guess is that the payload's ContentLength does not match the internal-string. XML uses UTF-8 escapes, so the payload could become larger. So on original string the representation could Content-Length could differ.
Maybe you calculate the Content-Length at a wrong place?

Related

Serializing using protobuf-net and sending as postdata in http

I'm using Protobuf-net to try and send a serialized object to a webapplication that I'm running in another project. The Serializer.Serialize<T>() method takes a Stream (to write to) and and instance of T (in this case, a list of a few objects that I set up to work with protobuf-net)
How do I go about doing this? Do I need to write to a file or can I send the stream as postdata somehow? Below you can see I'm using a string as the postdata.
My execute post method
public static void ExecuteHttpWebPostRequest(Uri uri,string postdata, int requestTimeOut, ref string responseContent)
{
if (string.IsNullOrEmpty(uri.Host))// || !IsConnectedToInternet(uri))
return;
var httpWebReq = (HttpWebRequest)WebRequest.Create(uri);
var bytePostData = Encoding.UTF8.GetBytes(postdata);
httpWebReq.Timeout = requestTimeOut*1000;
httpWebReq.Method = "POST";
httpWebReq.ContentLength = bytePostData.Length;
//httpWebReq.ContentType = "text/xml;charset=utf-8";
httpWebReq.ContentType = "application/octet-stream";
//httpWebReq.TransferEncoding=
//httpWebReq.ContentType = "application/xml";
//httpWebReq.Accept = "application/xml";
var dataStream = httpWebReq.GetRequestStream();
dataStream.Write(bytePostData, 0, bytePostData.Length);
dataStream.Close();
var httpWebResponse = (HttpWebResponse)httpWebReq.GetResponse();
// Get the stream associated with the response.
var receiveStream = httpWebResponse.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
var readStream = new StreamReader(receiveStream,Encoding.Default);
responseContent = readStream.ReadToEnd();
httpWebResponse.Close();
}
You can just serialize to the request:
Serializer.Serialize(dataStream, obj);
And equally, you can deserialize from receiveStream, if you choose.
Note, however, that protobuf data is not text, and should not be treated as such - very bad things happen if you try that.

Unable to Pass Image in HTTP POST in a HTTP Web Request in ASP.NET

I am having trouble converting an image into bytes and saving it in database.
Here is the description,
I have an image that will be send from a remote device to the web server using HTTP POST.
so what I am doing is I ask them to sent the image to me.
Since the data is sent in POST i assume they will send me the Bytes by converting the bytes into string using
byte[] img = FileUpload1.FileBytes;
Encoding enc = Encoding.ASCII;
string img = enc.GetString(img);
Then they make a WebRequest using HTTPWebRequest and append this image in HTTP POST.
The Whole Code for making the request ---
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
//Create the POST Data
FileUpload img = (FileUpload)imgUpload;
Byte[] imgByte = null;
if (img.HasFile && img.PostedFile != null)
{
imgByte = imgUpload.FileBytes;
}
string imgPh = null;
Encoding enc = Encoding.ASCII;
if (imgByte != null)
{
imgPh = enc.GetString(imgByte);
}
string postData = "sid=8062BD53EB4552AD6D0FBB7E5DC5B7AF&status=Y&uid=123456789012&fname=Dinesh Singh&lname=Malik&ftname=Balwan&yrbirth=1988&gender=Male&address1=Address1&address2=Address2&address3=Address3&address4=Address4&imagePh=" + imgPh;
byte[] post = Encoding.UTF8.GetBytes(postData);
//Set the Content Type
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = post.Length;
Stream reqdataStream = request.GetRequestStream();
// Write the data to the request stream.
reqdataStream.Write(post, 0, post.Length);
reqdataStream.Close();
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = null;
try
{
// Get the response.
response = request.GetResponse();
}
catch (Exception ex)
{
Response.Write("Error Occured.");
}
On the Page to which Request is made I am getting this image again into bytes using
Encoding enc = Encoding.ASCII;
byte[] imagePhoto = enc.GetBytes(postData["imageph"]);
From Here I save it into my Database
But when I retrieve the image using the Handler, it does not show the image.
The issue is the conversion of the image from byte[] to string and then converting string into byte[] at the Web Server. (Because when I save the image directly without this conversion using TestPage on server it shows the image.)
So What am I doing wrong in this.
Also is there any way in the above code to get the data of HTTP Post as received by the Web Server (retrieve HTTP Headers).
I want to retrieve this data received to sent it back to the Other Development to develop the request at the device in the same format as I am receiving in the HTTP Web Request URL
Any help would be appreciated.
Ok I think finally I figured it out.
What I did was -
Image -> byte[] -> Convert.ToBase64String -> Append The String Data to Post Request
At the Server-
Get the Post Data -> Convert.FromBase64String -> byte[] -> Insert into Database
Works Great...:)
Thanks

How to do httpPost to a webservice which accepts a byte array of a file using c#

I am working on an API kind of project,
I have wrote a WebMethod (not exactly. I am using MVC to create REST like API)
public UploadFileImage(string employeeId, byte[] imageBytes, string imageName)
{
// saves the imagebyte as an image to a folder
}
the web service would be consumed by a web app, or windows or even iphone or such portable stuffs. I am testing my web service using a web app, by simple httpPost.
string Post(Uri RequestUri, string Data)
{
try
{
HttpWebRequest request = HttpWebRequest.Create(RequestUri) as HttpWebRequest;
request.Method = "POST";
request.ContentType = IsXml.Checked ? "text/xml" : "application/x-www-form-urlencoded";
byte[] bytes = Encoding.ASCII.GetBytes(Data);
Stream os = null; // send the Post
request.ContentLength = bytes.Length; //Count bytes to send
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
HttpWebResponse httpWebResponse = (HttpWebResponse)request.GetResponse();
StreamReader streamReader = new StreamReader(request.GetResponse().GetResponseStream());
return streamReader.ReadToEnd();
}
catch (Exception ex)
{
return ex.Message;
}
}
This code works fine for evey method like, AddEmployee, DeleteEmployee etc. THe parameter Data is of form "Id=123&name=abcdefgh&desig=Developer",
How I call any other function is
Post(new Uri("http://localhost/addemployee"),"name=abcd&password=efgh")
where post is the function i wrote.
All good for all functions. Except that I dont know how to consume the above mentioned function UploadFileImage to upload an image?
Thanks
Try encoding the imageBytes as Base64.
From your code snippet is not too clear how you call UploadFileImage, that is how you convert its parameters tripplet into Data.
That is why my answer is quite generic:
In general, you'd better transfer your image file by
request.ContentType = "multipart/form-data; boundary=----------------------------" + DateTime.Now.Ticks.ToString("x");
Please allow me to refer you to a sample at StackOverflow on how to format a multipart request. I am sure that if you google, you shall find a lots of detailed examples and explanations as well.
I hope this helps :-)

Retrieve XML from HTTP POST Request Payload

I have an ActiveX that POSTs to the server (HTTP Handler) with a payload of a certain XML document.
Is there a better way to retrieve the payload into XML than the below?
private static byte[] RequestPayload()
{
int bytesToRead = HttpContext.Current.Request.TotalBytes;
return (HttpContext.Current.Request.BinaryRead(bytesToRead));
}
using (var mem = new MemoryStream(RequestPayload()))
{
var docu = XDocument.Load(mem);
}
Once I have the "docu" I can query using LINQ to XML.
Thanks
Simply load the XML from the InputStream of the Request e.g.
XDocument doc;
using (Stream input = HttpContext.Current.Request.InputStream)
{
doc = XDocument.Load(input);
}
there is no need for a MemoryStream in my view.

Sending and receiving binary data in Servlets

I'm attempting to write a Java Servlet to receive binary data requests and reply to them, using HttpServletRequest.getOutputStream() and HttpServletResponse.getInputStream(). This is for a project which involves having a request sent by a Silverlight client to which this servlet responds to through an HTTP POST connection. For the time being, to test the Servlet I'm implementing a client in Java which I'm more familiar with than Silverlight.
The problem is that in my test project I send the data from a Servlet client as a byte array and expect to receive a byte array with the same length -- only it doesn't, and instead I'm getting a single byte. Therefore I'm posting here the relevant code snippets in the hopes that you might point me where I'm doing wrong and hopefully provide relevant bibliography to help me further.
So here goes.
The client servlet handles POST requests from a very simple HTML page with a form which I use as front-end. I'm not too worried about using JSP etc, instead I'm focused on making the inter-Servlet communication work.
// client HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String firstName = (String) request.getParameter("firstname");
String lastName = (String) request.getParameter("lastname");
String xmlRequest = "<MyRequest><Person><Name Firstname=\""+firstName+"\" Lastname=\""+lastName+"\" /></Person></MyRequest>";
OutputStream writer = null;
InputStream reader = null;
try {
URL url = new URL("http://localhost:8080/project/Server");
URLConnection conn = url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
writer = conn.getOutputStream();
byte[] baXml = xmlRequest.getBytes("UTF-8");
writer.write(baXml, 0,baXml.length);
writer.flush();
// perhaps I should be waiting here? how?
reader = conn.getInputStream();
int available = reader.available();
byte[] data = new byte[available];
reader.read(data,0,available);
String xmlResponse = new String(data,"UTF-8");
PrintWriter print = response.getWriter();
print.write("<html><body>Response:<br/><pre>");
print.write(xmlResponse);
print.write("</pre></body></html>");
print.close();
} finally {
if(writer!=null)
writer.close();
if(reader!=null)
reader.close();
}
}
The server servlet handles HTTP POST requests. This is done by receiving requests the requests from a client Servlet for testing purposes above, but in the future I intend to use it for clients in other languages (specifically, Silverlight).
// server HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServetResponse response)
throws ServletException, IOException {
ServletInputStream sis = null;
try {
sis = request.getInputStream();
// maybe I should be using a BufferedInputStream
// instead of the InputStream directly?
int available = sis.available();
byte[] input = new byte[available];
int readBytes = sis.read(input,0,available);
if(readBytes!=available) {
throw new ServletException("Oops! readBytes!=availableBytes");
}
// I ONLY GET 1 BYTE OF DATA !!!
// It's the first byte of the client message, a '<'.
String msg = "Read "+readBytes+" bytes of "
+available+" available from request InputStream.";
System.err.println("Server.process(HttpServletRequest,HttpServletResponse): "+msg);
String xmlReply = "<Reply><Message>"+msg+"</Message></Reply>";
byte[] data = xmlReply.getBytes("UTF-8");
ServletOutputStream sos = response.getOutputStream();
sos.write(data, 0,data.length);
sos.flush();
sos.close();
} finally {
if(sis!=null)
sis.close();
}
}
I have been sticking to byte arrays instead of using BufferInputStreams so far because I've not decided yet if I'll be using e.g. Base64-encoded strings to transmit data or if I'll be sending binary data as-is.
Thank you in advance.
To copy input stream to output stream use the standard way:
InputStream is=request.getInputStream();
OutputStream os=response.getOutputStream();
byte[] buf = new byte[1000];
for (int nChunk = is.read(buf); nChunk!=-1; nChunk = is.read(buf))
{
os.write(buf, 0, nChunk);
}
The one thing I can think of is that you are reading only request.getInputStream().available() bytes, then deciding that you have had everything. According to the documentation, available() will return the number of bytes that can be read without blocking, but I don't see any mention of whether this is actually guaranteed to be the entire content of the input stream, so am inclined to assume that no such guarantees are made.
I'm not sure how to best find out when there is no more data (maybe Content-Length in the request can help?) without risking blocking indefinitely at EOF, but I would try looping until having read all the data from the input stream. To test that theory, you could always scan the input for a known pattern that occurs further into the stream, maybe a > matching the initial < that you are getting.

Resources