HttpWebRequest Send File with multipart/form-data for Windows Phone - c#

I have create an Csv File in my phone ( I have this content and this path ) and, url to post this csv...
string path = csv.path;
string content = csv.content;
string urlPost = csv.urlPost;
I want to post my File ( just one csv file ) with the HttpWebRequest, for windows phone, I saw lot of post for HttpWebRequest in C# , and never specific to windows Phone ( HttpWebRequest for windows phone doesn't have all method of "normal" HttpWebRequest) .
I have already saw the msdn page => http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
and this post for HttpWebRequest in c# Upload files with HTTPWebrequest (multipart/form-data) But I don't arrived to translate examples for windows phone.
I arrived to called my server ( with my Url) but, the file are never transmitted...
Also, I don't want use the RestSharp library.
My actually code =>
public void SentPostReport()
{
Uri uri = new Uri(csv.urlPost); //Url is string url
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
// My File content and path.
string pathReportFile = csv.path;
string CsvContent = csv.content;
// Transmitted The File ????
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadLine();
//DEBUG => affiche le résultat de la requête.
Debug.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
I have delete my code in the GetRequestStreamCallback's function , and replace by "// transmitted file ? "
I think it's the places where I have to send my file, but I don't find the solution to transmitted this.
I have testing with this code :
byte[] byteArray = Encoding.UTF8.GetBytes(CsvContent);
postStream.Write(byteArray, 0, byteArray.Length);
and other found in different forum, and I every times, teh call with my server is good, but file isn't transmitted...
Have you a solution for use HttpWebRequest and Stream for send my file in my server?
In advance : thanks!!

Well, I just found this project, is just a single helper class, is very simple and helpful.
MultipartHttpClient
Hope this helps

Related

Trying to do a GET web requisition but ProtocolViolationException was unhandled [duplicate]

I am new to silverlight. I am programming in Visual Studio 2010 for Windows phone.
I try to do HttpWebRequest but debugger says ProtocolViolationException.
This my code
private void log_Click(object sender, RoutedEventArgs e)
{
//auth thi is my url for request
string auth;
string login = Uri.EscapeUriString(this.login.Text);
string password = Uri.EscapeUriString(this.pass.Password);
auth = "https://api.vk.com/oauth/token";
auth += "?grant_type=password" + "&client_id=*****&client_secret=******&username=" + login + "&password=" + password + "&scope=notify,friends,messages";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.BeginGetRequestStream(RequestCallBack, request);//on this line debager say ProtocolViolationExceptio
}
void RequestCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
Stream stream = request.EndGetRequestStream(result);
request.BeginGetResponse(ResponceCallBack, request);
}
void ResponceCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = request.EndGetResponse(result) as HttpWebResponse;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string a =sr.ReadToEnd();
MessageBox.Show(a);
}
}
I think the problem is that you aren't using POST, but GET. Try this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.Method = "POST";
request.BeginGetRequestStream(RequestCallBack, request);
You aren't even doing anything with the request stream when you get it.
HttpWebRequest is assuming that the reason you tried to get it, was to write content to it (the only reason for getting it, after all).
Since you aren't allowed to include content in a GET request, it realises that the only thing you can do with that stream, is something that would violate the HTTP protocol. As a tool for using the HTTP protocol, it's its job to stop you making that mistake.
So it throws ProtocolViolationException.
Cut out the bit about the request stream - it's only for POST and PUT. Go straight to GetResponse() or BeginGetResponse() at that point.

C# HTTP request 401 and 500 error

I've been working on the Walmart API but I keep getting either the 401 error or the 500 error when I run the code
public void post()
{
byte[] data = Encoding.ASCII.GetBytes(
$"username={user}&password={password}");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://marketplace.walmartapis.com/v2/feeds?feedType=item");
request.Method = "POST";
request.Accept = "application/xml;";
request.ContentLength = data.Length;
request.Headers.Add("WM_SVC.NAME", "Walmart Marketplace");
request.Headers.Add(authId);
request.Headers.Add("WM_CONSUMER.ID", user);
request.Headers.Add( time);
request.Headers.Add(CorId);
using (Stream stream = request.GetRequestStream ())
{
stream.Write(data , 0, data.Length);
}
string responseContent = null;
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}
MessageBox.Show(responseContent);
}
where authID is a signature generated from a jar file provided by walmart
time is also generated from the jar file
CorID is a randomly generated number
and user is the user id.
here is the link that describes the header parameters. Did I miss something in my header?
https://developer.walmartapis.com/#getting-started
There are multiple problems with your request. First, you are submitting a feed, but sending it as an application/xml when it should be a multipart/form-data request. Beyond this, your headers aren't set up properly and there is currently a major problem with submitting multipart/form-data requests to Walmart using C#. I have not seen a post from anyone successfully sending a feed to Walmart via C#. I am currently using C# to execute a batch file that then fires a modified version of the Walmart Java SDK which is capable of sending the multipart/form-data requests.
The reponse below is for any request other than feeds. I would start with the example listed below to get familiar with how you need to set your headers up. This is going to work for the majority of Walmart interfacing, but if the request is a feed style request, you will either need to come up with a better solution to the multipart/form-data issue, use the Java SDK, or wait for the C# SDK. If someone reads this and has a better answer as to how to submit feeds via C# exclusively I would love to hear about it!
Here is an example of an application/xml request that works.
string timestamp = CurrentTimeMillis().ToString().Trim();
string query = #"orders/"+poID+"/acknowledge";
string request = v3BaseUrl + query; //Constructed URI
string stringToSign = consumerId + "\n" +
request.Trim() + "\n" +
"POST" + "\n" +
timestamp + "\n";
string signedString = signData(stringToSign); //Your signed string
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(request);
webRequest.Accept = "application/xml";
webRequest.ContentType = "application/xml";
webRequest.Method = "POST";
webRequest.Headers.Add("WM_SVC.NAME", "Walmart Marketplace");
webRequest.Headers.Add("WM_SEC.AUTH_SIGNATURE", signedString);
webRequest.Headers.Add("WM_CONSUMER.ID", consumerId);
webRequest.Headers.Add("WM_SEC.TIMESTAMP", timestamp.ToString().Trim());
webRequest.Headers.Add("WM_QOS.CORRELATION_ID", Guid.NewGuid().ToString());
webRequest.Headers.Add("WM_CONSUMER.CHANNEL.TYPE", channelType);
webRequest.ContentLength = 0;
webRequest.Timeout = Timeout.Infinite;
webRequest.KeepAlive = true;
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
success = true;
}
}

Windows Phone 8 Http request with custom header

I want to send a HTTP PUT request to a WCF server from Windows Phone 8, and for identification I have to send a custom header. (assume "mycustomheader" = "abc")
I was using WebClient so far, but the Webclient.Headers seems not to have an Add method, so it is not possible to send headers other then the ones in HttpRequestHeader enum. Is there any way to do this with WebClient?
I saw it is possible to set a custom header with HttpWebRequest class, but I just can't get it to do anything at all. My test code (basically the sample copied from http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx):
public void dosth()
{
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create("http://mycomputer/message");
wr.Method = "PUT";
wr.ContentType = "application/x-www-form-urlencoded";
wr.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), wr);
allDone.WaitOne();
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
string postData = "{'Command': { 'RequestType' : 'Status', 'Test' : '1' }}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
allDone.Set();
}
As I can see with wireshark: nothing is arriving at my computer (same url and everything works fine with WebClient .. except for the custom header). In debugging I can see the GetRequestStreamCallback being fired and running through. But it never arrives in the GetResponseCallback. Most stuff I find regarding this refers to methods like GetResponse() that seem not to be available on
Whats is the way to go here? Is it possible to get the HttpWebRequest to work, or is there some workaround to get the custom header set in WebClient or is there even another better way?
edit: webclient code:
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentLength] = data.Length.ToString();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(new Uri("http://mycomputer/message"), "PUT", data);
sends the correct data to the correct url. However setting custom header seems not to be possible. (even tried \r\n inside a header ... but this is not allowed and throws exception)
Where do you set the header?
Here is how to do it:
request.Headers["mycustomheader"] = "abc";

Why do I get ProtocolViolationException when I do BeginGetRequestStream

I am new to silverlight. I am programming in Visual Studio 2010 for Windows phone.
I try to do HttpWebRequest but debugger says ProtocolViolationException.
This my code
private void log_Click(object sender, RoutedEventArgs e)
{
//auth thi is my url for request
string auth;
string login = Uri.EscapeUriString(this.login.Text);
string password = Uri.EscapeUriString(this.pass.Password);
auth = "https://api.vk.com/oauth/token";
auth += "?grant_type=password" + "&client_id=*****&client_secret=******&username=" + login + "&password=" + password + "&scope=notify,friends,messages";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.BeginGetRequestStream(RequestCallBack, request);//on this line debager say ProtocolViolationExceptio
}
void RequestCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
Stream stream = request.EndGetRequestStream(result);
request.BeginGetResponse(ResponceCallBack, request);
}
void ResponceCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = request.EndGetResponse(result) as HttpWebResponse;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string a =sr.ReadToEnd();
MessageBox.Show(a);
}
}
I think the problem is that you aren't using POST, but GET. Try this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.Method = "POST";
request.BeginGetRequestStream(RequestCallBack, request);
You aren't even doing anything with the request stream when you get it.
HttpWebRequest is assuming that the reason you tried to get it, was to write content to it (the only reason for getting it, after all).
Since you aren't allowed to include content in a GET request, it realises that the only thing you can do with that stream, is something that would violate the HTTP protocol. As a tool for using the HTTP protocol, it's its job to stop you making that mistake.
So it throws ProtocolViolationException.
Cut out the bit about the request stream - it's only for POST and PUT. Go straight to GetResponse() or BeginGetResponse() at that point.

Send File in POST Request with Windows phone 7

I have create an "csv file" in my windows phone,
I want to post it, in a server, in the web and I don't find how I want to proceed for that,
I don't want just make a "post request" with parameters, I want to post my File in the server...
Actually, I'm connect to this server, but it don't find my file...
public void SentPostReport()
{
//Post response.
string url = this.CurentReportkPI.configXml.gw; // string url
Uri uri = new Uri(url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Accept = "application/CSV";
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
// I create My csv File
CreateCsv reportCsv = new CreateCsv();
string pathReportFile = reportCsv.CreateNewReport(this.report);
string CsvContent = reportCsv.ReadFile(pathReportFile);
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(CsvContent);
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
Debug.WriteLine("GetResponseCallback");
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadLine();
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
Have you an idea when I proceed for resolve my problem,and send my CSV File with my request ?
Thanks.
Not sure if this is the problem here, but on a POST request, you are supposed to set the ContentLength and ContentType ("application/x-www-form-urlencoded") headers, amongst other things...
Please check this "how-to" article on a fully correct POST request -- It's not for Windows Phone, but I think you'll still get the full ideia!
On the other hand, I'd suggest you just go with RestSharp that will solve all these problems for you!
you can do this easily using RestSharp or Hammock with the AddFile method. Here's an example of what i did for uploading a photo using Hammock:
var request = new RestRequest("photo", WebMethod.Post);
request.AddParameter("photo_album_id", _album.album_id);
request.AddFile("photo", filename, e.ChosenPhoto);
request.Client.BeginRequest(request, (restRequest, restResponse, userState) =>
{
// handle response
}

Categories