Why there's no Request.Content in ASP .NET MVC 5? - c#

How to get access to content data?
I can get Request.ContentLength , ContentType, but Content I can't.
I tried to add [FromBody] attribute before my string parameter, but it returns null anyway.
[HttpPost]
public string CreateItemType([System.Web.Http.FromBody] string json) // still returns null
{
var Content = Request.Content; // Error: 'HttpRequestBase' doesn't have a definition for 'Content'
if (IsAuthorized(Request) == false) return "Authorization Error"; ...
Are there some ways to access sent data?
My app for sending data:
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(Link);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
request.Headers.TryAddWithoutValidation("Authorization", ApiKey);
client.Timeout = TimeSpan.FromSeconds(10);
var MyResponse = await client.SendAsync(request);
MyResponse.EnsureSuccessStatusCode();
content = await MyResponse.Content.ReadAsStringAsync();
return content;
}
P.S: I could pass all the parameters into the request link, but my JSON-string is too big.

Related

How to split an HTTP Request Body in two parts?

I'm fairly new to use HTTPClient and sending REST requests to APIs, I'm currently practicing multipart upload using this Google Drive API endpoint:
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
There's an instruction that states there to split the request body into two parts, I tried to recreate this but was unable to do so.
https://developers.google.com/drive/api/guides/manage-uploads#multipart
Here's my current code:
async void UploadFile(StorageFile fileName)
{
using (HttpClient client = new HttpClient())
{
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(
new { name = fileName.Name, mimetype = fileName.ContentType });
// Create POST request
var requestMessage = new HttpRequestMessage(HttpMethod.Post, uploadFileEndpoint);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Add request body
requestMessage.Content = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.SendAsync(requestMessage);
string responseString = await response.Content.ReadAsStringAsync();
output(responseString);
}
}
Any help would be greatly appreciated, thank you!
According to the documentation on Perform a multipart upload (HTTP tab), you need the MultipartFormDataContent as suggested by #Jeremy.
There are a few things needed to perform/migrate:
Add AuthenticationHeaderValue into client.DefaultRequestHeaders.Authorization.
Create a StreamContent instance, fileStreamContent (which you have done) and specify its Headers.ContentType.
Create a StringContent instance, stringContent (which you have done).
Append both StreamContent and StringContent into the MultipartFormDataContent instance, formData.
Specify the formData's Headers.ContentType as requested in API docs.
Post the formData with await client.PostAsync(/* API Url */, formData);
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(fileName.ContentType);
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(new { name = fileName.Name, mimetype = fileName.ContentType });
var stringContent = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
// Create POST request
MultipartFormDataContent formData = new MultipartFormDataContent();
formData.Add(stringContent, "metadata");
formData.Add(fileStreamContent, "media");
formData.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.PostAsync(uploadFileEndpoint, formData);
string responseString = await response.Content.ReadAsStringAsync();
}

Rest API Post Json using C# with two parameters

I need to do a Post request on a REST api, the api accepts JSON data type. I have two parameters to include, startdate and enddate. Any guide in C#? Im getting error (415) Unsupported Media Type. I believe its because my post request doesnt have a proper json body
var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add(HttpRequestHeader.Authorization, "Bearer xxx");
request.ContentType = "application/json; charset=utf-8";
// Get response here
var response = request.GetResponse() as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine(response.ToString());
Console.ReadKey();
// ....
}
This is how I do it with an example of how to set a header.
using Newtonsoft.Json;
// e.g. update a user's email address via REST POST
dynamic user = new JObject();
user.Email = "testuser#test.com";
var json = user.ToString();
// json is then
// {"Email":"testuser#test.com"}
// and the json is POSTed to the appropriate REST url
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "user agent name");
var request = GetRequestMessage(uri, accessToken, json);
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
private HttpRequestMessage GetRequestMessage(string uri, string accessToken, string jsonPayload)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
{
Headers = { { "Authorization", $"Bearer {accessToken}" } }
};
httpRequestMessage.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
return httpRequestMessage;
}

Why HttpClient uses an incorrect requestUri in post request?

When I use HttpClient class to send a POST request to an API URL, it modifies the URL that I've passed to it. For example, when I use the main API URL the RequestUri is incorrect and I receive the not found response. This problem happens when I use api word in the URL !!
Concept:
The Incorrect, modified URL:
Url: https://sandbox-api.alopeyk.com/api/v2/order
Request Url: https://sandbox-api.alopeyk.com
The Correct, and expected URL (This is the one I specify)
Url: https://google.com/api/v2/order
Request Url: https://google.com/api/v2/order
Code:
public async Task<CreateOrderResponse> CreateOrderAsync(CreateOrderRequest request)
{
var endPoint = EndPointFactory<CreateOrderResponse>.Build(HttpMethod.Post);
var jsonString = JsonConvert.SerializeObject(request);
var url = new Uri("https://sandbox-api.alopeyk.com");
var encodedFrom = new StringContent(jsonString);
var httpClient = endPoint.GetHttpClient(url);
var httpResponse = await httpClient.PostAsync("api/v2/orders", encodedFrom).ConfigureAwait(false);
// when use api it's https://sandbox-api.alopeyk.com it should be https://sandbox-api.alopeyk.com/api/v2/orders
// when use other host name for example it's correct
var requesturl = httpResponse.RequestMessage.RequestUri;
return await httpResponse.Content.ReadAsAsync<CreateOrderResponse>().ConfigureAwait(false);
}
// in the EndPoint class
public HttpClient GetHttpClient(Uri url)
{
return new Http.HttpClientFactory().GetOrCreate(Url, Headers);
}
If you want to see HttpClientFactory it's here.
The HttpClient have a problem with my main hostname that it's https://sandbox-api.alopeyk.com
Your Uri must end with a slash like this:
var url = new Uri("https://sandbox-api.alopeyk.com/");
That's a rather silly restriction of HttpClient.
Try this code:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://sandbox-api.alopeyk.com");
HttpResponseMessage response = client.PostAsync("api/v2/orders", new StringContent(jsonString, Encoding.UTF8, "text/json")).Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var responseData = response.Content.ReadAsStringAsync().Result;
}
You can try with this code
HttpResponseMessage response = null;
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Post,"https://sandbox-api.alopeyk.com/api/v2/orders"))
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", /*token herer*/);
var data = new StringContent(JsonConvert.SerializeObject(request, Encoding.UTF8, "application/json"));
request.Content = data;
response = await client.SendAsync(request);
}
}

Sending serialized data in Get/Post Requests

Hi I have a method in my webservice as follows
[HttpGet]
public HttpResponseMessage RegenerateReport(/*string reportObject*/)
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StringContent("Operation completed.");
return result;
}
It works fine but i actually want to be able to send a serialized JSON object to this function.
Alternatively, I tried using [HttpPost] tag on this function and calling from my code as follows
var data = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(obj));
string _BaseUrl = ConfigurationManager.AppSettings["WebAPIBaseURL"];
HttpWebRequest request = WebRequest.Create(string.Format("{0}{1}",
_BaseUrl,
"test/RegenerateReport?FileName=" + RCFileName)) as HttpWebRequest;
// Set type to POST
request.Method = "Post";
request.ContentType = "application/xml";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
It returns
The requested resource does not support http method 'GET'.
Update
This error is now removed as i have added both tags [HttpGet] and [HttpPost] to my web method. Now the thing is how to pass serialized object to the web service method. Thanks!
If you want to submit some data in web service, you should always use [HttpPost].
I think your consumer is wrong and not doing a POST request. I typically use Microsoft.AspNet.WebApi.Client package and the sample code may look like this:
static async Task TestApiAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:33854/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var result = await client.PostAsync("api/School", "hello", new JsonMediaTypeFormatter());
result.EnsureSuccessStatusCode();
// if it something returns
string resultString = await result.Content.ReadAsAsync<string>();
Console.WriteLine(resultString);
}
}
Just substitute the parameters for your need (URL, type, body)
As told by #MacakM, while HttpClient seems to be the ultimate solution I am sharing the exact code that worked for me.
HttpClient _client = new HttpClient();
var apiParams = new Dictionary<string, string>();
apiParams.Add("FileName", RCFileName ?? string.Empty);
string _BaseUrl = ConfigurationManager.AppSettings["WebAPIBaseURL"];
_client.BaseAddress = new Uri(_BaseUrl);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = _client.GetAsync(string.Format("{0}{1}",
_BaseUrl,
"test/RegenerateReport?FileName=" + RCFileName)
);
if (response.IsCompleted)
_client.Dispose();//Dispose the client object

Call REST Service from WebAPi and transfer HttpResponseMessage

I have to call a REST Service from Web API.
Call and retrieve data works well but the return method crash.
I have tried several method that return an async HttpResponseMessage, but I can return this object as well (error socket on chrome ERR_SPDY_PROTOCOL_ERROR).
I've tried too with just a plain json as string, but no more success.
Here some tries :
[Route("{id}")]
public async Task<JObject> Get(string id)
{
dynamic client = new RestClient($"https://...../accounts/{id}/summary",
new Dictionary<string, string> {
//some KVP for access Rest API
});
//await client.Get() returns HttpResponseMessage 200 and Content is well populated
JObject result = JObject.FromObject(await client.Get());
return result;
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>());
//HttpResponseMessage result = await client.Get(); => HttpResponseMessage is well filled
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>()); => test with wrapping inside a new HttpResponseMessage but no more success
//using (var client = new HttpClient())
//{
// client.BaseAddress = new Uri($"https://....../v1/accounts/{id}/summary");
// client.DefaultRequestHeaders.Accept.Clear();
// client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HttpResponseMessage response = await client.GetAsync("");
// return Request.CreateResponse(HttpStatusCode.OK, response.Content.ReadAsAsync());
//}
}
Is there a simple method to retrieve json from Rest Service and transfer this as it is ?
If these calls are being performed in a Web API, and there is no logic being applied to the JSON Object, then there is little need to parse it before returning it as it will get serialized again when being returned, you can instead parse it on the front-end application and perform your logic there.
HttpClient has a method which returns the response body as a string, this is GetStringAsync. With the body returned as string, you can return that directly in your HttpResponseMessage
Here's an example using your HttpClient commented code.
[Route("{id}")]
public async Task<HttpResponseMessage> Get(string id)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri($"https://....../v1/accounts/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Fetch the response body as a string
// Resource URI added below
string responseContent = await client.GetStringAsync($"{id}/summary");
// Create our response object and set the content to its StringContent
var response =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(responseContent)};
// Return our HttpResponseMessage containing our json text
return response;
}
}
If you just want to transfer the json response from another API, you can use code like the following in Web API:
[HttpGet]
[Route("v1/test", Name = "test")]
public HttpResponseMessage GetTest()
{
UriBuilder uriBuilder = new UriBuilder($"https://...../...");
var webRequest = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
webRequest.Method = "GET";
webRequest.ContentType = "application/json; charset=utf-8";
webRequest.Accept = "application/json, text/javascript, */*";
using (var jsonResponse = (HttpWebResponse) webRequest.GetResponse())
{
var jsonStream = jsonResponse.GetResponseStream();
MemoryStream ms = new MemoryStream();
jsonStream.CopyTo(ms);
ms.Position = 0;
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
}
When the only thing needed is to support authentication or authorization features, i would prefer to use an API manager and not maintain this kind of code myself.

Categories

Resources