How to pass IFormFile from One Api to Another Api c# - c#

When trying to pass IFormFile from one api to another , I am getting a null value
Ex. Method (IFormFile form, Guid Id)
I tried adding the [FromForm] tag in front of the property of the api that I am calling but get a null value also tried using [FromBody] but get a HTTP 415 Unsupported Media Type client error
Api Trying to call:
["{Id:guid}/UploadData"]
public async Task<IActionResult> Upload([FromForm]IFormFile File, Guid Id)
How Im trying to pass the filo this api endpont
public async Task CreateEnterpriseLogo(IFormFile file, Guid Id)
{
MultipartFormDataContent multipartContent = new
MultipartFormDataContent();
var fileContent = new ByteArrayContent(GetFileArray(file));
multipartContent.Add(fileContent, "File",file.FileName);
var uri = $"{httppath}/{Id}/UploadData";
var response = await _client.PostAsync(uri, multipartContent);
if (!response.IsSuccessStatusCode)
{
throw new Exception(message: response.RequestMessage.ToString());
}

Related

Need to return attachment and JSON in get action method in API controller

I have a requirement that I need to send an attachment and JSON in a single get call.
[HttpGet]
[Route("IntakeByStudyIdandProjectNumber")]
[EnableCors("LocalhostPolicy")]
[EnableQuery]
public async Task<ActionResult> GetIntakebyStudyIdandProject()
{
IFormFile formFile = null;
return ok(await _manager.GetIntakeFormByIdandName(), formFile);
}
I am not sure which response type do I need to use to send both of them. For the files usually I use "FileContentResult" as the return type.

How to upload file outside or controller and not in IFormFile type

I use Mediatr for handling commands and queries in the Application projects which was sent from the WebApi project. In the WebApi project user sends to controller IFormFile. To handle IFormFile in the Application project I have to install aspnetcore.http.features. But I do not want this dependency in the Application project. How can I send the user file not in IFormFile to the handler of the Application project from the controller?
You can read the contents of the file into a byte array and pass the byte array as a parameter to your Mediatr request.
[HttpPost]
public async Task<IActionResult> Post([FromForm]IFormFile file)
{
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
var fileContents = stream.ToArray();
var result = await _mediator.Send(new YourMediatrRequest(fileContents));
return Ok(result);
}
}
public class YourMediatrRequestHandler : IRequestHandler<YourMediatrRequest, YourMediatrResponse>
{
public Task<YourMediatrResponse> Handle(YourMediatrRequest request, CancellationToken cancellationToken)
{
var fileContents = request.FileContents;
...more code
}
}

Web API [FromBody] always null

Im currently creating a Web API that writes into a table. Im using [FromBody] tag to pass the values for the table.
The problem is that the [FromBody] value is always null. Im using Advanced Rest Client to test my API.
public HttpResponseMessage Post(int id, [FromBody]string value)
{
//DO Something
}
The problem is in the type conversion. You are sending an array with one value containg a dictionary and trying to recieve a string in the method. ASP.NET can't cast your structure to string and use null as default value.
So, the simple way to test method is to pass a simple string in body. But the right way is to change the type of object passing into action method:
public HttpResponseMessage Post(int id, [FromBody]List<Dictionary<string,string>> value)
{
//DO Something
}
It’s strange to parse JSON manually when the system does it, but then you should pass string to the method. Just wrap your body to "" and you'll get a plain JSON in the method. Also you can read body manually via StreamReader:
public HttpResponseMessage Post(int id)
{
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
var plainBody = reader.ReadToEnd();
}
}
If you don't want the body deserialized, you can just read the string from the Request.Body property.
public Task<HttpResponseMessage> Post(int id)
{
var reader = new StreamReader(Request.Body);
var bodyString = await reader.ReadToEndAsync();
...
}

Web API HttpPost method always receives GET

I have a web api controller with a method
[HttpPost]
[Authorize]
[Route("[action]")]
public async Task<IActionResult> Authenticate(HttpRequestMessage msg)
{
//msg.Method is always GET
// msg.Content is null
}
I call it from my desktop application like this:
HttpClient client = new HttpClient(new HttpClientHandler(){AllowAutoRedirect = false});
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
await client.PostAsync(requestUrl, content);
But in the web api method the property msg.Method is always GET and msg.Content is null
Is it sort of redirect or another intentional behavior that every request turns into GET?
I tried to change it to
[Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend([FromBody]string request)
{
return Ok();
}
but got 'BadRequest' after call.
The only thing that works is to replace string with dynamic:
[Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend([FromBody]dynamic request)
{
return Ok();
}
Only POST requests are routed to your action. You just looking at the wrong place - you are trying to bind body of your request to HttpRequestMessage instance. Obviously, you are passing something else here.
If you are looking for request details, use the Request property of controller. It is populated from contoller context which is passed to the controller during activation:
[Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend()
{
// Request.Method is POST here
return Ok();
}
But you don't need to use it to get request content. Let Asp.Net do this work for you - declare a model class which has the same properties as the serialized object which you are sending and model binder will do deserialization work for you:
[Authorize]
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> C2dSend(YourModel blah)
{
// model will be populated automatically from request body
return Ok();
}
Note: There is an easier way to send json requests. You can use PostAsJsonAsync extension from System.Net.Http.Formatting.Extension

HttpClient call to web api method with integer parameter Returns error 404

I really can't see what I am doing wrong here. I am trying to call a asp.net core web api method that accepts an integer via HttpClient but it returns a 404 error.
HospitalController (Web API)
[HttpGet("{id}")]
[Route("GetById")]
public JsonResult Get(int id)
{
return Json(_hospitalService.Get(id));
}
HospitalController (MVC)
protected string url = "http://localhost:5001/api/Hospital";
[HttpGet]
public async Task<IActionResult> Edit(int id)
{
if (id.Equals(0))
return StatusCode(404);
var accessToken = await HttpContext.GetTokenAsync("access_token");
client.SetBearerToken(accessToken);
HttpResponseMessage responseMessage = await client.GetAsync(url + "/GetById/" + id); //returns 404 error here.
if (responseMessage.IsSuccessStatusCode)
{
var responseData = responseMessage.Content.ReadAsStringAsync().Result;
var hospital = JsonConvert.DeserializeObject<Hospital>(responseData);
var hospitalVM = Mapper.Map<HospitalViewModel>(hospital);
return View(hospitalVM);
}
return View("Error");
}
I have a POST method in the same controller in MVC that works. But this GET method returns a 404 and I can't seem to know why.
There are two route templates being used in the api according to
[HttpGet("{id}")] //Matches GET api/Hospital/5
[Route("GetById")] //Matches GET api/Hospital/GetById
neither of which match what is being called
http://localhost:5001/api/Hospital/GetById/5
Http{Verb} attribute is usually used on RestFul APIs.
When building a REST API, it's rare that you will want to use [Route(...)] on an action method. It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.
Reference Routing to Controller Actions
update the route template on the web api to map to the desired route
[Route("api/[controller]")]
public class HospitalController : Controller {
//...code removed for brevity
//Matches GET api/Hospital/GetById/5
[HttpGet("GetById/{id:int}")]
public IActionResult Get(int id) {
return Ok(_hospitalService.Get(id));
}
}
Also HttpClient is meant to be used asynchronously, so the MVC controller would also need to be refactored as mixing blocking calls .Result can cause deadlocks
protected string url = "http://localhost:5001/api/Hospital";
[HttpGet]
public async Task<IActionResult> Edit(int id) {
if (id.Equals(0))
return StatusCode(404);
var accessToken = await HttpContext.GetTokenAsync("access_token");
client.SetBearerToken(accessToken);
HttpResponseMessage responseMessage = await client.GetAsync(url + "/GetById/" + id);
if (responseMessage.IsSuccessStatusCode) {
var responseData = await responseMessage.Content.ReadAsStringAsync();
var hospital = JsonConvert.DeserializeObject<Hospital>(responseData);
var hospitalVM = Mapper.Map<HospitalViewModel>(hospital);
return View(hospitalVM);
}
return View("Error");
}

Categories

Resources