Return Image using IHttpActionResult - asp.net-web-api2

I have a requirement to return an image from a WebApi using IHttpActionResult instead of HttpResponseMessage. How this can be achieved & what are the accept & content type headers need to be passed?
Thanks!!

I was actually looking for a solution to send an image resides on internet from web api but I am returning local thumbnail images from my web api with the following code;
[HttpGet]
[Route("thumbnail/{userId}/{fileName}")]
public IHttpActionResult GetThumbnail()
{
var mediaRoot = System.Web.HttpContext.Current.Server.MapPath("~/media");
var imgPath = Path.Combine(mediaRoot, "images", userId, "thumbnail", fileName);
var fileInfo = new FileInfo(imgPath);
return !fileInfo.Exists
? (IHttpActionResult)NotFound()
: new FileResult(fileInfo.FullName);
}
Hope this helps
Edit: You should create a custom IHttpActionResult to retun images,
It seems i have created a custom IHttpActionResult to return images and here is the post that i got this code from > Custom IHttpActionResult

This would be a basic way:
[HttpGet]
[Route("test")]
public IHttpActionResult GetImageTest()
{
var stream = File.OpenRead(#"C:\picture.jpg");
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
response.Content.Headers.ContentLength = stream.Length;
return ResponseMessage(response);
}

Related

How to send and receive multipart/form-data containing files in .NET Core?

Using .NET Core 3.1, I have the following Http client which builds a HTTP POST containing multipart/form-data body:
public async Task SendRequest(string randomString, IFormFileCollection files)
{
var form = new MultipartFormDataContent();
form.Add(new StringContent(randomString), "randomString");
foreach (var file in files)
{
var stream = new MemoryStream();
await file.CopyToAsync(stream, cancellationToken);
form.Add(new StreamContent(stream), "files");
}
using var request = new HttpRequestMessage(HttpMethod.Post, $"api/endpoint")
{
Content = form
};
await _httpClient.SendAsync(request);
}
The receiving controller looks like this:
[Consumes("multipart/form-data")]
[HttpPost]
public async Task ReceiveForm([FromForm] RequestModel request)
{
//Do stuff
}
RequestModel looks like this:
public class RequestModel
{
[JsonPropertyName("randomString")]
public string RandomString { get; set; }
[JsonPropertyName("files")]
public IFormFileCollection Files { get; set; }
}
The problem I am seeing is that requestModel.RandomString gets populated, but the requestModel.Files does not - it is null.
What am I doing wrong?
thanks for the perfect code in example!
You should set both parameters (name and fileName) to files - form.Add(new StreamContent(stream), "files", "files");
Method description:
Parameters:
content: The HTTP content to add to the collection.
name: The name for the HTTP content to add.
fileName: The file name for the HTTP content to add to the collection.
This is my example:
var fileName = "files";
var byteArrayContent = new ByteArrayContent(fileBytes1);
form.Add(byteArrayContent, fileName, fileName);
var stream = new MemoryStream(fileBytes2);
form.Add(new StreamContent(stream), fileName, fileName);
Results:

Could not post value to web API using IFormFile

i have a web application that does an action to upload image to api
the code like this
[HttpPost]
public async Task<IActionResult> Upload([FromForm] UploadModel model)
{
var upload = AccountApi.UploadFile(model);
return Ok("OK");
}
public static object UploadFile(UploadModel model)
{
RestClient client = InitClient();
request.Resource = "Account/UploadFile";
request.Method = Method.POST;
request.AddJsonBody(model);
IRestResponse<object> response = client.Execute<object>(request);
return response.Data;
}
public class UploadModel
{
public long UserId { get; set; }
public string Token { get; set; }
public IFromFile File { get; set; }
}
and there's a web API to handle Rest request above
the code like this
[HttpPost("UploadFile")]
public async Task<object> UploadFileAction(UploadModel model)
{
// the code handle upload file request here
return "Success";
}
my issue is the UploadModel model in web application contains the right value that requested from front-end (UserId = 10, Token = "eyJ..........", File = [object])
but when it posted to API, the 3 properties in UploadModel didn't get the value posted from web application (UserId = 0, Token = null, File = null)
could you help me to find the solution for this. Thanks all
I found the solution myself.
instead of using IFormFile to post, I serialized the image file to a base64 string and post it over API. and in API, I convert it to File object
Thanks for following my question

How to create an ASP.NET Core API controller action for HttpPost that can accept a request that has content of type MultipartFormDataContent

I am working on an ASP.NET Core 2.0 API in VS2017.
I want to create a controller action for an HTTP Post method that accept string and byte[] values that I will then use to create records in my SQL database.
From what I understand, if I want to post both string data and a byte[] that represents a file, I have to use MultipartFormDataContent as the type of content in the request from my client.
So, on the API controller action, how is that mapped? Can I have a DTO class in the API that has properties for both the string values and the byte[] value and have it passed into the API controller action via the [FromBody]UploadsDto dto
For example, have a DTO class like this...
public class UploadFileRecordForCreationDto
{
public int LocationId { get; set; }
public string FileName { get; set; }
public byte[] UploadedFile { get; set; }
}
Then have a controller action with this signature...
[HttpPost(Name = "CreateUploadFileRecord")]
public IActionResult CreateUploadFileRecord([FromBody]UploadFileRecordForCreationDto dto)
{
...
...
...
return CreatedAtRoute("GetUploadedFileFile", new { id = linkedResourceToReturn["Id"] }, linkedResourceToReturn);
}
And then have that API action accept a request created using something similar to what I am doing with this test console application on the client side;
static async Task CreateUploadFileRecordAsync()
{
httpClient.BaseAddress = new Uri("https://localhost:44369");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string relativeUrl = "/api/UploadFilesManager";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, relativeUrl);
HttpResponseMessage response = new HttpResponseMessage();
using (var content = new MultipartFormDataContent("--UploadTest"))
{
var values = new[]
{
new KeyValuePair<string,string>("LocationId","1"),
new KeyValuePair<string,string>("FileName","TestFile-01.txt"),
};
foreach (var keyvaluepair in values)
{
content.Add(new StringContent(keyvaluepair.Value, Encoding.UTF8, "application/json"), keyvaluepair.Key);
}
var fileContent = new ByteArrayContent(File.ReadAllBytes(#"C:\testfile-01.txt"));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue(DispositionTypeNames.Attachment)
{
Name = "UploadedFile",
FileName = "testfile-01.txt"
};
content.Add(fileContent);
request.Content = content;
response = await httpClient.SendAsync(request);
}
if (response.IsSuccessStatusCode)
{
string result = response.Headers.Location.ToString();
Console.WriteLine("Success:\n");
Console.WriteLine($"New Record Link: [{result}]\n");
}
else
{
Console.WriteLine($"Failed to create new UploadFile record. Error: {0}\n", response.ReasonPhrase);
}
}
If it doesn't just map to a DTO in the FromBody, can anyone provide an example of how to deal with this use case?

Return an image from asp.net web api core as IActionResult

What is the best way to return an image file as IActionResult while using asp.net web api core?
I tried returning a base64 string and it works fine. But not considered as efficient.
Is there a way using which we can return an image file object itself as IActionResult.
You can use the various overloads of the File() function in controllers that inherit from Controller or ControllerBase.
For example, you can do:
return File("~/Images/photo.jpg", "image/jpeg");
This uses a virtual path, other options include giving it a byte array or a Stream. You can also give a download file name as a third argument if that is needed.
[Route("getProductImage/v1")]
[HttpGet]
public async Task<IActionResult> getProductImage(GetProductImageQueryParam parammodel)
{
using (HttpClient client = new HttpClient())
{
MNimg_URL = MNimg_URL + parammodel.modelname;
HttpResponseMessage response = await client.GetAsync(MNimg_URL);
byte[] content = await response.Content.ReadAsByteArrayAsync();
//return "data:image/png;base64," + Convert.ToBase64String(content);
return File(content, "image/png", parammodel.modelname);
}
}
In .net core web api you can use the above code
here GetProductImageQueryParam is a class with input parameters
A File result is called FileContentResult in NET Core 3.x.
You can return image using return file with stream or bytes format or using its image path.
There are few overloaded methods for return File(//parameters); which you can use it in mvc controller's action method.
API Controller
[Route("api/[controller]")]
public class FileController : Controller {
//GET api/file/id
[HttpGet("{id}"]
public async Task<IActionResult> GetFile(string id) {
var stream = await {{//__get_stream_here__//}};
var response = File(stream, "application/octet-stream"); // FileStreamResult
return response;
}
}
or
var imageFileStream = System.IO.File.OpenRead("// image path");
return File(imageFileStream, "image/jpeg");
Hope this will help you.

Need Help Getting HTML out of Razor View in ASP.NET Core With Action Result Filter

I'm following Steve Smith's article on how to use Filters in ASP.NET Core. Specifically, I want to get the HTML after it has been processed by the razor view engine. I've created an action filter and decorated my controller as follows yet I still get an empty html string from the stream. I think it has something to do with using the Result and not the Context but I'm not sure. Here is my code:
[AppendToHtmlBodyFilter]
public IActionResult Videos()
{
return View();
}
public void OnResultExecuted(ResultExecutedContext context)
{
Stream originalStream = context.HttpContext.Response.Body;
using (MemoryStream newStream = new MemoryStream())
{
context.HttpContext.Response.Body = newStream;
context.HttpContext.Response.Body = originalStream;
newStream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(newStream);
var htmlData = reader.ReadToEnd();
}