I have a method in my API that returns a HttpResponseMessage:
[HttpGet, HoodPeekAuthFilter]
public HttpResponseMessage GlobalOverview()
{
try
{
StatsRepo _statsRepo = new StatsRepo();
string file = _statsRepo.IncidentData().AsCSVString();
if (file == null)
{
return Request.CreateResponse(HttpStatusCode.NoContent);
}
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StringContent(file);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "GlobalOverview.csv";
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError);
}
}
In my MVC Web Apllication i have a controller Action that needs to call the API and return the file:
[Authorize]
[HttpGet]
public HttpResponseMessage GlobalOverview()
{
HttpResponseMessage file = new HttpResponseMessage();
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(this.UserName + ':' + this.Password)));
Task<HttpResponseMessage> response = httpClient.GetAsync("api.someDomain/Reporting/GlobalOverview");
file = response.Result;
}
return file;
}
If i access the API url directly it prompts me for a username and password, and then the Save File dialogue appears, and i can download the file.
If i navigate to the Action in my Web Application then i get the following response output to screen:
StatusCode: 200,
ReasonPhrase: 'OK',
Version: 1.1,
Content: System.Net.Http.StreamContent,
Headers: { Pragma: no-cache X-SourceFiles: = XXXXXXX
Content-Disposition: attachment;
filename=GlobalOverview.csv
Content-Type: application/octet-stream Expires: -1
I take it i need to return a FileResult, but i have no clue as to how to convert the HttpResponseMessage to a FileResult.
In your MVC controller you can try returning a FileResult, and use the File() method reading the response of your API as byte array.
[Authorize]
[HttpGet]
public FileResult GlobalOverview()
{
HttpResponseMessage file = new HttpResponseMessage();
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(this.UserName + ':' + this.Password)));
Task<HttpResponseMessage> response = httpClient.GetAsync("api.someDomain/Reporting/GlobalOverview");
file = response.Result;
}
return File(file.Content.ReadAsByteArrayAsync().Result, "application/octet-stream", "GlobalOverview.csv");
}
Related
I have a Web API which uploads the File content to the server.
[HttpPost]
[Route("SaveFileContent")]
public async Task<FileResponse> SaveFileContent([FromForm] SaveFileContentRequest request)
{
return await _service.SaveFile(request);
}
This is my call to the API:
public async Task<FileResponse> SaveFileContent(SaveFileContentRequest request)
{
try
{
var uri = "https://www.mycompanyurl.com";
using (var client = new HttpClient())
{
using (var form = new MultipartFormDataContent())
{
using (var fileContent = new ByteArrayContent(request.File))
{
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "file", request.FileName);
form.Add(new StringContent(request.MemberId), "MemberId);
form.Add(new StringContent(request.Country), "Country);
client.BaseAddress = new Uri(uri);
HttpResponseMessage response = await client.PostAsync("/api/Document/SaveFileContent", form);
FileResponse result = JsonConvert.DeserializeObject<FileResponse>(response.Content.ReadAsStringAsync().Result);
return result;
}
}
}
}
}
I get this response at PostAsync():
{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Date: Sun, 21 Apr 2013 12:00:03 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 165
Content-Type: application/json; charset=utf-8
}}
When I try to run the API in my local - and use the localhost uri -
var uri = "http://localhost:51515";
It is working fine and getting the 200 OK response.
try to use the full route
[Route("~/api/Document/SaveFileContent")]
public async Task<FileResponse> SaveFileContent([FromForm] SaveFileContentRequest request)
I'm developing an API who makes searches on a stock photos and now I need to deliver files(Download method) so I created the following code:
public HttpResponseMessage Download(string id)
{
Download download = new Download(id, apiUser);
byte[] myDataBuffer = download.DownloadImage();
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(myDataBuffer);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
The bytes are received correctly on method DownloadImage(), the problem is in the HttpResponseMessage return, I upload in release website and through another project I have the following code who calls the API:
public static void DownloadNewImage(string id)
{
var request = new RestRequest(Method.GET);
request.Resource = "Home/Download";
request.AddParameter("id", id);
RestResponse response = Execute(request, "website-url");
}
private static RestResponse Execute(RestRequest request, string url)
{
var cliente = new RestClient(url);
cliente.FollowRedirects = false;
var response = cliente.Execute(request);
return (RestResponse)response;
}
When i debug the response, I receive the following:
See that ContentLength = -1 and when i open the Content text the retur is this:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content:
System.Net.Http.ByteArrayContent, Headers:
{
Content-Type: application/octet-stream
}
I think that is something wrong in the Download method from API who returns HttpResponseMessage, and some parameters is wrong someone can give me help?
I'm trying to upload image and json in one request using c# code, but server always returns 400- bad request. Executing same request using fiddler returns status code 200. help...
Here is my fiddler code :
------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="application/json" Content-Type: application/json
{"type": "Personal","comments": ["Lorem", "Ipsum" ] }
------WebKitFormBoundary7MA4YWxkTrZu0gW-- Content-Disposition: form-data; name="fieldNameHere"; filename="1111.jpg"
Content-Type: image/jpeg
<#INCLUDE C:\Users\user\Desktop\New folder\1111.jpg#>
And implementation in c#:
var boundary = "Upload----" + DateTime.Now.Ticks.ToString();
MultipartFormDataContent form = new MultipartFormDataContent(boundary);
StringContent content = new StringContent(bodyJson);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
form.Add(content, "application/json");
var imageContent = new ByteArrayContent(image);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
form.Add(imageContent, "image/jpeg", "image.jpg");
var responseTask = _httpClient.PostAsync(url, form).Result;
the response is always same :
You can pass the parameter as a string content , check the below sample.
public async Task<JObject> ExecutePostAsync(Stream myStreem, string url, string token, string parameter1, string parameter2, string parameter3)
{
try
{
using (var content = new MultipartFormDataContent("----MyBoundary"))
{
using (var memoryStream = myStreem)
{
using (var stream = new StreamContent(memoryStream))
{
content.Add(stream, "file", Guid.NewGuid().ToString() + ".jpg");
content.Add(new StringContent(parameter1), "parameter1");
content.Add(new StringContent(parameter3), "parameter2");
content.Add(new StringContent(parameter3), "parameter3");
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var responce = await client.PostAsync(url, content);
string contents = await responce.Content.ReadAsStringAsync();
return (JObject.Parse(contents));
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
In API get the data from FORM request
public async Task<IHttpActionResult> UploadFile()
{
string parameter1 = HttpContext.Current.Request.Form["parameter1"];
string parameter2 = HttpContext.Current.Request.Form["parameter2"];
string parameter3 = HttpContext.Current.Request.Form["parameter3"];
}
I have 2 MVC sites. One (A) is posting to another (B).
MVC site A:
using (var handler = new WebRequestHandler())
{
handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient(handler))
{
using (var formData = new MultipartFormDataContent())
{
StreamContent fileStreamContent = new StreamContent();
formData.Add(fileStreamContent, "file", HttpUtility.UrlEncode(Path.GetFileName("some test path")));
var fileReceiveURL = "URL(B)\SomeController\PostFile";
HttpResponseMessage response = client.PostAsync(fileReceiveURL, formData).Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception("Not able to send file to (B). Didn't get a successful response from server.");
}
}
}
}
MVC site B (SomeController):
[HttpPost]
public HttpResponseMessage PostFile(HttpPostedFileBase file)
{
\\ for testing purpose, just return a bad request response code
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
But at (A). the response (breakpoint at [HttpResponseMessage response...] ) is always "StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1" no matter what HttpStatusCode I set to (B) to send back.
How can I send HttpStatusCode between 2 MVC sites?
Instead of checking the response object...
HttpResponseMessage response = client.PostAsync(fileReceiveURL, formData).Result;
response will always return 200 OK.
need to check
HttpResponseMessage response = await client.PostAsync(fileReceiveURL, formData);
string responseString = await response.Content.ReadAsStringAsync();
response.Content contains the proper HttpStatusCode from site B.
We are using asp.net web api odata entitysetcontroller to get user profiles. The url that represents a single user profile looks like this
http://www.domain.com/api/org/staff(123)
Now bussiness asked us to provide user image as part of the user profile. So I added a odata action method to the exisitng controller.
var staff = builder.EntitySet<Contact>("staff"); //regiester controller
var staffAction = staff.EntityType.Action("picture"); //register action method
staffAction.Returns<System.Net.Http.HttpResponseMessage>();
The odata action method in controller as below
[HttpPost]
public HttpResponseMessage Picture([FromODataUri] int key)
{
var folderName = "App_Data/Koala.jpg";
string path = System.Web.HttpContext.Current.Server.MapPath("~/" + folderName);
using (FileStream mem = new FileStream(path,FileMode.Open))
{
StreamContent sc = new StreamContent(mem);
HttpResponseMessage response = new HttpResponseMessage();
response.Content = sc;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
response.Content.Headers.ContentLength = mem.Length;
response.StatusCode = HttpStatusCode.OK;
return response;
}
}
I tried the following url to test and the method executed successfully. However the problem is that I always recieve the error message with status 504 as a final response.
http://www.domain.com/api/org/staff(123)/picture
"ReadResponse() failed: The server did not return a response for this request."
I think the problem is with closing the FileStream.
Do not close the stream as Web API's hosting layers take care of closing it. Also, you need
not set the content-length explicitly.StreamContent sets this for you.
[HttpPost]
public HttpResponseMessage Picture([FromODataUri] int key)
{
var folderName = "App_Data/Koala.jpg";
string path = System.Web.HttpContext.Current.Server.MapPath("~/" + folderName);
StreamContent sc = new StreamContent(new FileStream(path,FileMode.OpenRead));
HttpResponseMessage response = new HttpResponseMessage();
response.Content = sc;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
response.StatusCode = HttpStatusCode.OK;
return response;
}