Send Json as body and file webrequest - c#

How to send both body and also a file?
From the API Guide: "Upload Requests are submitted with multiple parts: body (request) and file buffer (file)."
I know how to send only a Json as body, but I need now to seng Json as body and also a file.
My code looks something like:
const string WEBSERVICE_URL = "https://myurl.com";
var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data;boundary=12345678912345678912345678";
webRequest.Headers.Add("Authorization:7786FFFGFDDDP");
And:
string json="{"\some json"\ :\"here\" }"
using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
{
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)webRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
But how to send both file and body together? I mean I want also to upload some file wih path #c:\\myFile.txt

I need to do this in a Xamarin application. Post an image to a web api with token based authentication. I made some changes in code to be posible use in a web application.
public async void SendFile()
{
using (System.IO.FileStream stream = System.IO.File.Open(#"c:\file.txt", System.IO.FileMode.Open))
{
var content = new System.Net.Http.MultipartFormDataContent();
content.Add(new System.Net.Http.StreamContent(stream),
"\"file\"",
"Path to your file (ex: c:\temp\file.txt");
await PostItemAsyncWithToken("url to post", content, "accessToken");
}
}
public async System.Threading.Tasks.Task<bool> PostItemAsyncWithToken(string url, System.Net.Http.HttpContent content, string accessToken)
{
try
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return true;
}
else
{
return false;
}
}
}
catch (System.Exception ex)
{
throw new System.Exception("Error message", ex);
}
}

Related

Refactor HttpWebRequest to HttpClient?

How would I convert this to HttpClient? What I'm looking to do is submit a Tweet to the Twitter api and get the response as Json. The HttpWebRequest is working fine but I just want to port it to HttpClient. I made an attempt at it in the second code example, but it's not actually sending or receiving the response.
HttpWebRequest request = null;
WebResponse response = null;
string responseCode = String.Empty;
try
{
string postBody = "status=" + EncodingUtils.UrlEncode(status);
request = (HttpWebRequest)HttpWebRequest.Create(resource_url);
request.ServicePoint.Expect100Continue = true;
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
request.ServicePoint.ConnectionLimit = 1;
request.Headers.Add("Authorization", authHeader);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(postBody);
}
}
using (response = request.GetResponse())
{
response.ContentType = "application/json";
responseCode = ((HttpWebResponse)response).StatusCode.ToString();
}
}
catch (WebException ex)
{
if (ex.Status != WebExceptionStatus.NameResolutionFailure)
{
request.Abort();
request = null;
}
throw ex;
}
return responseCode;
This is what I've tried to get it work:
private async Task<string> MakeWebRequest1(string status, string resource_url, string authHeader)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.Credentials = CredentialCache.DefaultCredentials;
clientHandler.PreAuthenticate = true;
clientHandler.AllowAutoRedirect = true;
string responseCode = "";
string postBody = "status=" + EncodingUtils.UrlEncode(status);
var request = new HttpRequestMessage()
{
RequestUri = new Uri(resource_url),
Method = HttpMethod.Post,
};
request.Headers.Add("Authorization", authHeader);
// request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
request.Content = new StringContent(postBody, Encoding.UTF8,"application/x-www-form-urlencoded");//CONTENT-TYPE header
using (HttpClient client = new HttpClient(clientHandler))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
// Stream stuff = await client.GetStreamAsync(resource_url);
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
if(response.StatusCode == HttpStatusCode.OK)
{
responseCode = "OK";
}
}
}
clientHandler.Dispose();
return responseCode;
}
enter code here
I've tried to add another parameter to the request and it's always coming back as 401 unauthorized. I'm trying to create a Twitter thread. If I remove the in_reply_to_status_id then it's fine.
data = new Dictionary<string, string> {
["status"] = "#username + status,
["in_reply_to_status_id"] = "1167588690929115136"
};
The Twitter API describes it here https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
Reference You're using HttpClient wrong to understand why a static client is being used.
static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
HttpClientHandler clientHandler = new HttpClientHandler {
Credentials = CredentialCache.DefaultCredentials,
PreAuthenticate = true,
AllowAutoRedirect = true
};
return new HttpClient(clientHandler);
});
private async Task<string> PostStatusRequestAsync(string status, string resource_url, string authHeader) {
using (var request = new HttpRequestMessage(HttpMethod.Post, resource_url)) {
request.Headers.TryAddWithoutValidation("Authorization", authHeader);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new Dictionary<string, string> {
["status"] = status
};
request.Content = new FormUrlEncodedContent(data);
using (HttpResponseMessage response = await client.Value.SendAsync(request)) {
return response.StatusCode.ToString();
}
}
}
Note the use of the FormUrlEncodedContent for the request body, which will encode and concatenate the data as well as take care of the mime type header
...but it's not actually sending or receiving the response.
Ensure that the above is not invoked as a synchronous blocking call, like .Result, which could cause a deadlock.
For example, an async event handler can be used to make the async call
public async void onButtonClick(object sender, EventArgs args) {
//Non-blocking call
var tweetRequestCode = await PostStatusRequestAsync(TweetText, AuthUtils.GetResourceUrl(), AuthUtils.GetWebRequestHeader()));
//back on UI thread
//...
}
Reference Async/Await - Best Practices in Asynchronous Programming

Xamarin Forms Json Service Insert Data

I want to add a record to the json service in my application. How can I do this via Service Url. Here is my code.
CustomerModel customer = new CustomerModel();
customer.Name = entryCompanyName.Text;
customer.Title = entryCompanyTitle.Text;
customer.PhoneNumber = entryTelephone.Text;
customer.FaxNumber = entryFax.Text;
customer.Email = entryEmail.Text;
customer.CityId = 6444;
string json = JsonConvert.SerializeObject(customer);
string sContentType = "application/json";
string path = "service url";
HttpClient Client = new HttpClient();
var task = Client.PostAsync(path, new StringContent(json.ToString(), Encoding.UTF8, sContentType));
I'm trying M. Wiśnicki's solution, but I took this error
I did not get an error when I added System.net :( Where do i make mistakes?
This worked for me
public static async Task<string> PostEntityToApi<T>(string yourMethodUrl, T yourModel)
{
try
{
if (_httpClient == null)
{
_httpClient = new HttpClient { BaseAddress = new Uri(yourWebSiteUrl) };
}
var stringContentInput = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(new Uri(yourWebSiteUrl. + apiUrl), stringContentInput);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
var stringAsync = await response.Content.ReadAsStringAsync();
LoggingManager.Error("Received error response: " + stringAsync);
return stringAsync;
}
catch (Exception exception)
{
return null;
}
}
You can use WebRequest, this sample working for me, i use it in my app.
This is System.Net.WebRequest class, here you find doc.
public async Task<string> PostSample(object data, string uri)
{
// Create an HTTP web request using the URL:
var request = (HttpWebRequest) WebRequest.Create(new Uri(uri));
request.ContentType = "application/json";
request.Method = "POST";
var itemToSend = JsonConvert.SerializeObject(data);
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
streamWriter.Write(itemToSend);
streamWriter.Flush();
streamWriter.Dispose();
}
// Send the request to the server and wait for the response:
using (var response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (var stream = response.GetResponseStream())
{
var reader = new StreamReader(stream);
var message = JsonConvert.DeserializeObject<string>(reader.ReadToEnd());
return message;
}
}
}

How to pass the File Data from C# Console application to WebApi?

I am trying to call the Web api method for saving the File Data.When I debug Webapi method I found that ContentLength is not coming as correct, because of this when i am retrieving the file it is showing error as corrupted file.
My Class method is :-
using (var formData = new MultipartFormDataContent())
{
HttpContent stringContent = new StringContent(file);
formData.Add(stringContent, "file", file);
formData.Add(new StringContent(JsonConvert.SerializeObject(file.Length)), "ContentLength ");
HttpResponseMessage responseFile = client.PostAsync("Report/SaveFile?docId=" + docId, formData).Result;
}
My Web api method is :-
[HttpPost]
public HttpResponseMessage SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var httpRequest = HttpContext.Current.Request;
bool IsSuccess = true;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
HttpPostedFile postedFile = httpRequest.Files[file];
// Initialize the stream.
Stream myStream = postedFile.InputStream;
myStream.Position = 0;
myStream.Seek(0, SeekOrigin.Begin);
var _item = CorrectedReportLibrary.Services.ReportService.SaveFile(myStream,docId);
response = Request.CreateResponse<bool>((IsSuccess)
? HttpStatusCode.OK
: HttpStatusCode.NoContent,
IsSuccess);
}
}
}
catch (Exception ex)
{
Theranos.Common.Library.Util.LogManager.AddLog(ex, "Error in CorrectedReportAPI.Controllers.SaveDocument()", null);
return Request.CreateResponse<ReportDocumentResult>(HttpStatusCode.InternalServerError, null);
}
return response;
}
How can I set the ContentLength from C# class method?
It looks a bit strange that you use ContentLength as the second parameter on the StringContent class. It is suppose to be which encoding you want to use, for example
new StringContent(content, Encoding.UTF8). I don't think it is the content length that is the issue here.
StringContent class
I guess since it is a file you want to upload, you already have the file read as a stream, so I usually do something like this:
Client:
private async Task UploadFile(MemoryStream file)
{
var client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(file));
var result = await client.PostAsync("Report/SaveFile?docId=" + docId, content);
}
Edit. Since it's a multipartform it's easier to let the framework handle the details. Try something like this:
Server:
[HttpPost]
public async Task<HttpResponseMessage> SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var filedata = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach(var file in filedata.Contents)
{
var fileStream = await file.ReadAsStreamAsync();
}
response = Request.CreateResponse<bool>(HttpStatusCode.OK, true);
}
catch (Exception ex)
{
response = Request.CreateResponse<bool>(HttpStatusCode.InternalServerError, false);
}
return response;
}
At Last I found the solution no need to change the web api service,
issue was from client where I was directly passing the file data, Now the modified
working code is like this:-
using (var formData = new MultipartFormDataContent())
{
var bytes = File.ReadAllBytes(file);
formData.Add(new StreamContent(new MemoryStream(bytes)), "file", file);
HttpResponseMessage responseFile = client.PostAsync("ReportInfo/SaveFile?docId=" + docId, formData).Result;
}

POST Request UWP

I writing UWP app.
I need to send POST request with json to server
Here is my code for downloading JSON and writing to value:
public async void AllOrders_down()
{
string url = "http://api.simplegames.com.ua/index.php/?wc_orders=all_orders";
var json = await FetchAsync(url);
List<RootObject> rootObjectData = JsonConvert.DeserializeObject<List<RootObject>>(json);
OrdersList = new List<RootObject>(rootObjectData);
}
public async Task<string> FetchAsync(string url)
{
string jsonString;
using (var httpClient = new System.Net.Http.HttpClient())
{
var stream = await httpClient.GetStreamAsync(url);
StreamReader reader = new StreamReader(stream);
jsonString = reader.ReadToEnd();
}
return jsonString;
}
How I need to send POST request with this json to server?
Thank's for help.
Here is an example Post request that I have used in a UWP application.
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"http://test.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/api/testendpoint";
try
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(yourPocoHere), Encoding.UTF8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
string jsonResponse = await response.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception)
{
//Could not connect to server
//Use more specific exception handling, this is just an example
}
}
You should be using httpClient.PostAsync().

POST request in UWP not sending

I writing app for UWP
I receive json from back end like this:
string url = "http://api.simplegames.com.ua/index.php/?wc_orders=all_orders";
{
string jsonString;
using (var httpClient = new System.Net.Http.HttpClient())
{
var stream = await httpClient.GetStreamAsync(url);
StreamReader reader = new StreamReader(stream);
jsonString = reader.ReadToEnd();
}
return jsonString;
}
I try to send POST request like this
OrdersList = new List<RootObject>(rootObjectData);
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"http://api.simplegames.com.ua");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/post_from_local.php";
try
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(OrdersList), Encoding.UTF8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
string jsonResponse = await response.Content.ReadAsStringAsync();
Debug.WriteLine(jsonResponse);
//do something with json response here
}
}
catch (Exception)
{
//Could not connect to server
//Use more specific exception handling, this is just an example
}
}
But, Back end dev said that he see empty row, but data is not received.
Thank's for help. Where is my error?
Change this line:
var stream = await httpClient.GetStreamAsync(url);
to:
var stream = httpClient.GetStreamAsync(url).Result;

Categories

Resources