How to properly post data using begin/end GetRequestStream and callbacks - c#

I'm trying to post a piece of data but it seems to be getting caught and hangs (but not throwing an error).
internal IAsyncResult RequestGet<TPostType>(Action<string> callback, string path, TPostType value)
{
var http = (HttpWebRequest)WebRequest.Create(Connection.GetUri(path).Uri);
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
var parsedContent = JsonConvert.SerializeObject(value);
var encoding = new ASCIIEncoding();
var bytes = encoding.GetBytes(parsedContent);
return http.BeginGetRequestStream(ar =>
{
try
{
var stream = http.EndGetRequestStream(ar);
stream.Write(bytes, 0, bytes.Length);
stream.Close();
http.BeginGetResponse(body =>
{
// its around here that it hangs.
var response = http.EndGetResponse(ar);
var s = response.GetResponseStream();
ReadStream(callback, s);
}, null);
}
catch (WebException webex)
{
WebResponse errResp = webex.Response;
using (Stream respStream = errResp.GetResponseStream())
{
Console.WriteLine(new StreamReader(respStream).ReadToEnd());
}
}
}, null);
}
There were a few times when it didn't hang but told me that the request body was missing, however I didn't make any progress beyond that. Could someone please inform me as to what I'm doing wrong?
The ReadStream method works for GET requests, but for context:
private static IAsyncResult ReadStream(Action<string> callback, Stream stream)
{
var buffer = new byte[5000];
var asyncResult = stream.BeginRead(buffer, 0, 5000, ar2 =>
{
try
{
callback(Encoding.UTF8.GetString(buffer, 0, 5000));
}
catch (Exception ex)
{
// do better error handling
Console.WriteLine("exception reading stream");
Console.WriteLine(ex);
}
}, null);
return asyncResult;
}
For more context on how its being used:
public IAsyncResult BeginGetChainPart(Action<BlockData.BlockList> callback, int height)
{
var asyncResult = new HttpConnector(Connection).RequestGet(body =>
{
callback(JsonConvert.DeserializeObject<BlockData.BlockList>(body));
}, "/local/chain/blocks-after", new BlockData.BlockHeight { Height = height });
return asyncResult;
}

found the solution, posting in case anyone comes across the same issue:
internal IAsyncResult RequestGet<TPostType>(Action<string> callback, string path, TPostType value)
{
var http = (HttpWebRequest)WebRequest.Create(Connection.GetUri(path).Uri);
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
var parsedContent = JsonConvert.SerializeObject(value);
var encoding = new ASCIIEncoding();
var bytes = encoding.GetBytes(parsedContent);
return http.BeginGetRequestStream(ar => {
try
{
var stream = http.EndGetRequestStream(ar);
stream.Write(bytes, 0, bytes.Length);
stream.Close();
var response = http.GetResponse();
var responseStream = response.GetResponseStream();
ReadStream(callback, responseStream);
}
catch (WebException webex)
{
WebResponse errResp = webex.Response;
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
}, null);
}

Related

how to return a xlsx file using memorystream web api

I am successfully making a web request, creating xlsx file and saving it to a directory. I would like to stream it and return it to the client without actually saving it on the server.
this is what i am currently using, it works fine
private string generateStudyTemplate(string requestId)
{
var serviceUrl = ConfigurationManager.AppSettings["serviceUrl"];
// create webRequest
HttpWebRequest webRequest = createWebRequest(serviceUrl + "/" + requestId);
// begin async call to web request
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request
var filename = string.Format("{0}.xlsx", "NewWorkbook");
string physicalPath = HttpContext.Current.Server.MapPath("/FilesForExport");
string relativePath = Path.Combine(physicalPath, filename).Replace("\\", "/");
var filePath = relativePath;
// var filePath = directory + "\\NewWorkbook.xlsx";
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
var str = webResponse.GetResponseStream();
var inBuf = new byte[webResponse.ContentLength];
var bytesToRead = Convert.ToInt32(inBuf.Length);
var bytesRead = 0;
while (bytesToRead > 0)
{
var n = str.Read(inBuf, bytesRead, bytesToRead);
if (n == 0)
break;
bytesRead += n;
bytesToRead -= n;
}
var fstr = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
fstr.Write(inBuf, 0, bytesRead);
fstr.Close();
}
return filePath;
}
private static HttpWebRequest createWebRequest(string url)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "GET";
return webRequest;
}
Here is what I have put together from some other examples.
public HttpResponseMessage GenerateMarketStudyResult([FromBody]Result id)
{
if (id.requestId == null)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest));
}
var serviceUrl = ConfigurationManager.AppSettings["serviceUrl"];
var streamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
{
try
{
HttpWebRequest webRequest = createWebRequest(serviceUrl + "/" + id.requestId);
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (MemoryStream memoryStream = new MemoryStream())
{
var str = webResponse.GetResponseStream();
var inBuf = new byte[webResponse.ContentLength];
var bytesToRead = Convert.ToInt32(inBuf.Length);
var bytesRead = 0;
while (bytesToRead > 0)
{
var n = str.Read(inBuf, bytesRead, bytesToRead);
if (n == 0)
break;
bytesRead += n;
bytesToRead -= n;
}
memoryStream.Write(inBuf, 0, bytesRead);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
outputStream.Close();
}
});
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
streamContent.Headers.ContentDisposition.FileName = "reports.xlsx";
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = streamContent
};
return result;
}
I am not getting any exceptions, but the xlsx file is returning with 0bytes.
The breakpoint here
memoryStream.Write(inBuf, 0, bytesRead);
here is the javascript serving the returned file
$http.post('/api/GenerateMarketStudyResult/', Result, { responseType: 'arraybuffer' })
.success(function (response, status, headers, config) {
saveAs(new Blob([response], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), 'reports.xlsx');
})
shows that the
bytesRead = 112336
I assume that you write a web service which acts as a proxy between your JavaScript and some third party web service.
First of all, if you use at least .NET 4.0, you can use the Stream.CopyTo method to copy a stream to another.
So instead of this:
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
var str = webResponse.GetResponseStream();
var inBuf = new byte[webResponse.ContentLength];
var bytesToRead = Convert.ToInt32(inBuf.Length);
var bytesRead = 0;
while (bytesToRead > 0)
{
var n = str.Read(inBuf, bytesRead, bytesToRead);
if (n == 0) break;
bytesRead += n;
bytesToRead -= n;
}
var fstr = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
fstr.Write(inBuf, 0, bytesRead);
fstr.Close();
}
You could write:
using (var webResponse = webRequest.EndGetResponse(asyncResult))
using (var fstr = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
webResponse.GetResponseStream().CopyTo(fstr);
}
Second, assuming you use WCF to build a web service, you could pipe the response to a memory stream, and return it. (dont forget to reset the stream's position after you finished writing)
Put together:
[WebGet(UriTemplate = "GenerateMarketStudyResult/{id}")]
public Stream GenerateMarketStudyResult(string id)
{
var serviceUrl = ConfigurationManager.AppSettings["serviceUrl"];
// create webRequest
HttpWebRequest webRequest = createWebRequest(serviceUrl + "/" + id);
// begin async call to web request
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI
asyncResult.AsyncWaitHandle.WaitOne();
var memStream = new MemoryStream();
// var filePath = directory + "\\NewWorkbook.xlsx";
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
webResponse.GetResponseStream().CopyTo(memStream);
}
memStream.Position = 0;
var response = WebOperationContext.Current.OutgoingResponse;
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.ContentLength = (int)memStream.Length;
return memStream;
}
EDIT:
You didn't copy the contents of the memoryStream to the outputStream. You can omit the memoryStream. Try this:
public HttpResponseMessage GenerateMarketStudyResult([FromBody]Result id)
{
if (id.requestId == null)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest));
}
var serviceUrl = ConfigurationManager.AppSettings["serviceUrl"];
var streamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
{
try
{
HttpWebRequest webRequest = createWebRequest(serviceUrl + "/" + id.requestId);
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
webResponse.GetResponseStream().CopyTo(outputStream);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
outputStream.Close();
}
});
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
streamContent.Headers.ContentDisposition.FileName = "reports.xlsx";
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = streamContent
};
return result;
}

Adding parameters to an HttpWebRequest

This question has been asked a million times, and yet none of the responses work for me. The one I was most excited about was Http Post for Windows Phone 8 but because it requires delegates, it's not right for my code... the Postdata function is called from repositories, it would be nice to get a response straight from this function!
How do I add post parameters to this code? I've been trying to get it to work for a good 10 hours now.
// Repository code
string url = "/bla/bla/" + blaId + "/";
Dictionary<string, string> postParams = new Dictionary<string, string>();
postParams.Add("value", message);
string response = await BlaDataContext.PostData(url, postParams);
// ...
public static async Task<string> PostData(string url, Dictionary<String, String> postParams)
{
HttpWebRequest request = WebRequest.CreateHttp(APIURL + url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
postParams.Add("oauth_token", Contract.AccessToken); // where do I add this to the request??
try
{
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
Debug.WriteLine(response.ContentType);
Stream responseStream = response.GetResponseStream();
string data;
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
return data;
}
catch (Exception e)
{
// whatever
}
}
HttpWebRequest request = WebRequest.CreateHttp("" + url);
//we could move the content-type into a function argument too.
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
postParams.Add("oauth_token", ""); // where do I add this to the request??
try
{
//this is how you do it
using(var stream = await request.GetRequestStreamAsync())
{
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(string.Join("&", postParams.Select(pp => pp.Key + "=" + pp.Value)));
await stream.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
}
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
Debug.WriteLine(response.ContentType);
System.IO.Stream responseStream = response.GetResponseStream();
string data;
using (var reader = new System.IO.StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
return data;
}
Async Await HttpWebRequest Extensions:
public static class HttpExtensions
{
public static Task<Stream> GetRequestStreamAsync(this HttpWebRequest request)
{
var tcs = new TaskCompletionSource<Stream>();
try
{
request.BeginGetRequestStream(iar =>
{
try
{
var response = request.EndGetRequestStream(iar);
tcs.SetResult(response);
}
catch (Exception exc)
{
tcs.SetException(exc);
}
}, null);
}
catch (Exception exc)
{
tcs.SetException(exc);
}
return tcs.Task;
}
public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse =
(HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
}
With the extensions, I think it's a little cleaner.
You need to write the parameters to the request body.
You could use an extension method like this one:
public static void AddFormData(this HttpWebRequest request, IDictionary<string, string> data)
{
using (var memStream = new MemoryStream())
using (var writer = new StreamWriter(memStream))
{
bool first = true;
foreach (var d in data)
{
if (!first)
writer.Append("&");
writer.Write(Uri.EscapeDataString(d.Key));
writer.Write("=");
writer.Write(Uri.EscapeDataString(d.Value));
first = false;
}
writer.Flush();
request.ContentLength = memStream.Length;
memStream.Position = 0;
using (var reqStream = request.GetRequestStream())
{
memStream.CopyTo(reqStream);
}
}
}
Call it like this:
request.AddFormData(postParams);

WP8 HttpWebRequest Post Not Working

I have a Windows Phone Application and I I am trying to post data in JSON format to a WCF application. Although the connection is made, the server returns with a custom message with
This is the C# code:
ReportSightingRequest.Instance.Source = Source.IPhone;
var jsonData = JsonConvert.SerializeObject(ReportSightingRequest.Instance);
var uri = new Uri("urlGoesHere", UriKind.Absolute);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = jsonData.Length;
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
This is the WCF Interface:
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[Description("Description.")]
Response.Response ReportSighting(ReportSightingRequest sighting);
This is the implementation:
public Response ReportSighting(ReportSightingRequest sightingRequest)
{
var response = new Response();
if (sightingRequest == null || sightingRequest.TypeId == null)
{
response.Status = ResponseStatus.InvalidArguments;
response.Message = "Request is null or no type has been supplied.";
return response;
}
...
}
When I call the ReportSighting method form the phone, I get a "Request is null or no type has been supplied" message. The strange thing is that I AM sending a TypeId and the sightingRequest object on the WP8 side is definitely not null when i'm sending it. When I put a breakpoint on the jsonData, it has everything in it. The ReportSightingRequest object too is exactly the same as the ReportSightingRequest in the WCF application.
It almost feels like that the object isn't being serialized. That's the only thing I can think of.
Does anyone have any ideas/suggestions?
Update
I've noticed that i'm actually not sending over the object. Shawn Kendrot's Answer seems to make sense but when I integrate his code, it returns with a Not Found error.
Update
The following code works in a Console App:
var jsonData = "a hard coded JSON string here";
var uri = new Uri("a url goes here", UriKind.Absolute);
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.Method = "POST";
webRequest.ContentType = "application/json; charset=utf-8";
webRequest.ContentLength = jsonData.Length;
webRequest.BeginGetRequestStream(ar =>
{
try
{
using (var os = webRequest.EndGetRequestStream(ar))
{
var postData = Encoding.UTF8.GetBytes(jsonData);
os.Write(postData, 0, postData.Length);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
webRequest.BeginGetResponse(
ar2 =>
{
try
{
using (var response = webRequest.EndGetResponse(ar2))
using (var reader = new StreamReader(response.GetResponseStream()))
{
var received = reader.ReadToEnd();
//Console.WriteLine(received);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}, null);
}, null);
Update
I have changed my code in WP8 to match that of Shawn Kendrot's solution. The problem which I am facing here is that I get a Not Found error message:
webRequest.BeginGetRequestStream(ar =>
{
try
{
using (var os = webRequest.EndGetRequestStream(ar))
{
var postData = Encoding.UTF8.GetBytes(jsonData);
os.Write(postData, 0, postData.Length);
}
}
catch (Exception ex)
{
MessageBox.Show("Unsuccessful");
}
webRequest.BeginGetResponse(
ar2 =>
{
try
{
using (var response = webRequest.EndGetResponse(ar2))
using (var reader = new StreamReader(response.GetResponseStream()))
{
var received = reader.ReadToEnd();
}
}
catch (Exception ex)
{
MessageBox.Show("Unsuccessful");
}
}, null);
}, null);
I get a:
{System.UnauthorizedAccessException: Invalid cross-thread access.
at MS.Internal.XcpImports.CheckThread()
at MS.Internal.XcpImports.MessageBox_ShowCore(String messageBoxText, String caption, UInt32 type)
at System.Windows.MessageBox.ShowCore(String messageBoxText, String caption, MessageBoxButton button)
at System.Windows.MessageBox.Show(String messageBoxText)
at Notify.Logic.WebServices.<>c_DisplayClass2.b_1(IAsyncResult ar2)
at System.Net.Browser.ClientHttpWebRequest.<>c_DisplayClass1d.b_1b(Object state2)}
When I try to do `MessageBox.Show(ex.Message);
Update
I have fixed the issue with the MessageBox.Show error message.
The webRequest.Headers object has the following:
{Content-Type: application/json; charset=utf-8;}
Your sightingRequest is null because you are not sending any data. To send data using a WebRequest, you need to use the BeginGetRequestStream method. This method allows you to package the data.
var webRequest= (HttpWebRequest)WebRequest.Create(uri);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
webRequest.ContentLength = jsonData.Length;
webRequest.BeginGetRequestStream(ar =>
{
try
{
using (Stream os = webRequest.EndGetRequestStream(ar))
{
var postData = Encoding.UTF8.GetBytes(jsonData);
os.Write(postData, 0, postData.Length);
}
}
catch (Exception ex)
{
// Do something, exit out, etc.
}
webRequest.BeginGetResponse(
ar2 =>
{
try
{
using (var response = webRequest.EndGetResponse(ar2))
using (var reader = new StreamReader(response.GetResponseStream()))
{
string received = reader.ReadToEnd();
}
}
catch (Exception ex)
{
// Do something, exit out, etc.
}
}, null);
}, null);

WP7 app never exits BeginGetResponse and goes into the callback function

I have the following code:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
//Console.WriteLine("Please enter the input data to be posted:");
//string postData = Console.ReadLine();
string postData = "my data";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
IAsyncResult result =
(IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private 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.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
allDone.Set();
Dispatcher.BeginInvoke((Action)(() => Debug.WriteLine("George")));
}
However when my code hits BeginGetResponse it never exits (and I do not hit a breakpoint in the GetResponseCallback function). I tried adding the BeginInvoke call, but I still never enter this method. This code works in a windows console app - it's on Windows Phone 7 that it doesn'teorg
Can anyone see what I am doing wrong?
Thanks.
If you have created the HttpWebRequest on the UI thread, then make sure you don't block the UI thread, otherwise you can deadlock.
The sample from the desktop .NET you have linked isn't optimized for the current phone networking stack. You should change the code so that you create the HttpWebRequest on a background thread.
I can't see what's wrong with your code (maybe a complete example of what you're trying to do may help) but here's a simple working example of a way of performing the action you want to do.
It posts some data to a URI and then passes the repsonse to a callback function:
Simply execute like this (use of a BackgroundWorker is not necessary but is recommended)
var bw = new BackgroundWorker();
bw.DoWork += (o, args) => PostDataToWebService("http://example.com/something", "key=value&key2=value2", MyCallback);
bw.RunWorkerAsync();
Here's the callback function it refers to:
(You can change this however is appropriate to your needs.)
public static void MyCallback(string aString, Exception e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (e == null)
{
// aString is the response from the web server
MessageBox.Show(aString, "success", MessageBoxButton.OK);
}
else
{
MessageBox.Show(e.Message, "error", MessageBoxButton.OK);
}
});
}
Here's the actual method:
public void PostDataToWebService(string url, string data, Action<string, Exception> callback)
{
if (callback == null)
{
throw new Exception("callback may not be null");
}
try
{
var uri = new Uri(url, UriKind.Absolute);
var req = HttpWebRequest.CreateHttp(uri);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
AsyncCallback GetTheResponse = ar =>
{
try
{
var result = ar.GetResponseAsString();
callback(result, null);
}
catch (Exception ex)
{
callback(null, ex);
}
};
AsyncCallback SetTheBodyOfTheRequest = ar =>
{
var request = ar.SetRequestBody(data);
request.BeginGetResponse(GetTheResponse, request);
};
req.BeginGetRequestStream(SetTheBodyOfTheRequest, req);
}
catch (Exception ex)
{
callback(null, ex);
}
}
and here are the extension/helper methods it uses:
public static class IAsyncResultExtensions
{
public static string GetResponseAsString(this IAsyncResult asyncResult)
{
string responseString;
var request = (HttpWebRequest)asyncResult.AsyncState;
using (var resp = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
using (var streamResponse = resp.GetResponseStream())
{
using (var streamRead = new StreamReader(streamResponse))
{
responseString = streamRead.ReadToEnd();
}
}
}
return responseString;
}
public static HttpWebRequest SetRequestBody(this IAsyncResult asyncResult, string body)
{
var request = (HttpWebRequest)asyncResult.AsyncState;
using (var postStream = request.EndGetRequestStream(asyncResult))
{
using (var memStream = new MemoryStream())
{
var content = body;
var bytes = System.Text.Encoding.UTF8.GetBytes(content);
memStream.Write(bytes, 0, bytes.Length);
memStream.Position = 0;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
postStream.Write(tempBuffer, 0, tempBuffer.Length);
}
}
return request;
}
}

How to make a HTTP PUT request?

What is the best way to compose a rest PUT request in C#?
The request has to also send an object not present in the URI.
using(var client = new System.Net.WebClient()) {
client.UploadData(address,"PUT",data);
}
My Final Approach:
public void PutObject(string postUrl, object payload)
{
var request = (HttpWebRequest)WebRequest.Create(postUrl);
request.Method = "PUT";
request.ContentType = "application/xml";
if (payload !=null)
{
request.ContentLength = Size(payload);
Stream dataStream = request.GetRequestStream();
Serialize(dataStream,payload);
dataStream.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string returnString = response.StatusCode.ToString();
}
public void Serialize(Stream output, object input)
{
var ser = new DataContractSerializer(input.GetType());
ser.WriteObject(output, input);
}
protected void UpdateButton_Click(object sender, EventArgs e)
{
var values = string.Format("Name={0}&Family={1}&Id={2}", NameToUpdateTextBox.Text, FamilyToUpdateTextBox.Text, IdToUpdateTextBox.Text);
var bytes = Encoding.ASCII.GetBytes(values);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("http://localhost:51436/api/employees"));
request.Method = "PUT";
request.ContentType = "application/x-www-form-urlencoded";
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
var response = (HttpWebResponse) request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
UpdateResponseLabel.Text = "Update completed";
else
UpdateResponseLabel.Text = "Error in update";
}
How to use PUT method using WebRequest.
//JsonResultModel class
public class JsonResultModel
{
public string ErrorMessage { get; set; }
public bool IsSuccess { get; set; }
public string Results { get; set; }
}
// HTTP_PUT Function
public static JsonResultModel HTTP_PUT(string Url, string Data)
{
JsonResultModel model = new JsonResultModel();
string Out = String.Empty;
string Error = String.Empty;
System.Net.WebRequest req = System.Net.WebRequest.Create(Url);
try
{
req.Method = "PUT";
req.Timeout = 100000;
req.ContentType = "application/json";
byte[] sentData = Encoding.UTF8.GetBytes(Data);
req.ContentLength = sentData.Length;
using (System.IO.Stream sendStream = req.GetRequestStream())
{
sendStream.Write(sentData, 0, sentData.Length);
sendStream.Close();
}
System.Net.WebResponse res = req.GetResponse();
System.IO.Stream ReceiveStream = res.GetResponseStream();
using (System.IO.StreamReader sr = new
System.IO.StreamReader(ReceiveStream, Encoding.UTF8))
{
Char[] read = new Char[256];
int count = sr.Read(read, 0, 256);
while (count > 0)
{
String str = new String(read, 0, count);
Out += str;
count = sr.Read(read, 0, 256);
}
}
}
catch (ArgumentException ex)
{
Error = string.Format("HTTP_ERROR :: The second HttpWebRequest object has raised an Argument Exception as 'Connection' Property is set to 'Close' :: {0}", ex.Message);
}
catch (WebException ex)
{
Error = string.Format("HTTP_ERROR :: WebException raised! :: {0}", ex.Message);
}
catch (Exception ex)
{
Error = string.Format("HTTP_ERROR :: Exception raised! :: {0}", ex.Message);
}
model.Results = Out;
model.ErrorMessage = Error;
if (!string.IsNullOrWhiteSpace(Out))
{
model.IsSuccess = true;
}
return model;
}

Categories