net core file uploading vis postman loading indefinitely - .net-core

[HttpPost, DisableRequestSizeLimit]
[AllowAnonymous]
public async Task<IActionResult> UploadFile()
{
var formCollection = await Request.ReadFormAsync();
var file = formCollection.Files.First();
//TODO: Implement the logic
return Ok();
}
Above is the Backend code. I am trying to upload a file via postman but the request is not hitting the action and getting no errors and loading forever.
I am working with .NET 5

You should set the Body to form-data, in Postman
From there, set the KEY as File, and select a file for the VALUE field.

Related

Uploading File (IfromFile) via HttpClient To webApi

Need help. I am trying to save or uploud a file (IFormFile) from a Project Web to the Web Api, consuming the web api via httpClient. I am getting the following error: System.NotSupportedException: The collection type 'Microsoft.AspNetCore.Http.IHeaderDictionary' on 'Microsoft.AspNetCore.Http.IFormFile.Headers' is not supported.enter image description here
enter image description here
NotSupportedException: The collection type 'Microsoft.AspNetCore.Http.IHeaderDictionary' on 'Microsoft.AspNetCore.Http.IFormFile.Headers' is not supported.
It seems that you are serializing a FormFile, which cause the above issue.
I am trying to save or uploud a file (IFormFile) from a Project Web to the Web Api, consuming the web api via httpClient.
public async Task<IActionResult> Online([FromForm]CandidaturaAddModel model)
{
var formContent = new MultipartFormDataContent();
formContent.Add(new StringContent(model.Senha), "Senha");
formContent.Add(new StringContent(System.Text.Json.JsonSerializer.Serialize(model.AnoLectvo)), "AnoLectvo");
//...
//for other properties, such as Email, Genero etc
//...
formContent.Add(new StreamContent(model.Foto.OpenReadStream()), "Foto", Path.GetFileName(model.Foto.FileName));
_httpClient.BaseAddress = new Uri("https://localhost:xxxx/");
var response = await _httpClient.PostAsync("/api/xxx/CandidaturaAdd", formContent);
if (response.IsSuccessStatusCode)
{
//....
}
Test Result

How to validate request before file upload using ASP.NET Core

I have this code that uploads a file.
My problem is that AuthorizationCheck fires only after the file is uploaded.
If the file is larger than 20MB the AuthorizationCheck will not fire at all and the request will return 404.
Is it possible to validate the request headers before the file steam is sent?
If the request is not authorized then the file should be blocked from uploading to the server.
Also it is not clear why when I upload a large file it is being uploaded fully and only then 404 is being returned...
[RequestSizeLimit(21_000_000)]
[Authorize(Policy = "AuthorizationCheck")]
public async Task<IActionResult> Upload(IFormFile file)
{
using (var stream = file.OpenReadStream())
{
await StoreFileAsync(stream);
}
}
[RequestSizeLimit(21_000_000)] limit your resquest can't exceed 20MB, you may use [DisableRequestSizeLimit] instead.
In addition, there's also a limit that's imposed by IIS, which is 30MB by default. When this size limit is exceeded, IIS itself generates a 404 response. To change the limit of IIS, you should custom a Web.configure.
For more details, you can refer to this answer.
Updata
You can access the request headers in a custom middleware :
app.Use(async (context, next) =>
{
var header = context.Request.Headers["XXX"];
//do something
await next();
});

Sending both files and model from Angular 4 to ASP.NET Core backend

I've been trying to make a form that contains both file inputs (in this case images) and text inputs. Text inputs are part of the model which I want to send to server. On the backend I'm using ASP.NET Core 2.0.
Here is my backend code:
[HttpPost]
public async Task<IActionResult> PostEditProfile([FromForm] EditProfileViewModel model, IFormFile profileImage, IFormFile bannerImage)
{
//Some code
}
When I call this API using Postman (where I set model's properties and images in form-data), everything works fine. But when I try to call it using Angular code, all the parameters are null. Here is my Angular 4 code:
var formData = new FormData();
for (var propertyName in editProfile) {
if (editProfile[propertyName]){
formData.append(propertyName, editProfile[propertyName].toString());
}
}
formData.append('profileImage', profileImage);
formData.append('bannerImage', bannerImage);
return this.authHttp.post(this.baseUrl + 'api/Account/PostEditProfile', formData)
.toPromise()
.then(response => {
var userInfo = response.json() as UserInfo;
this.setUserInfo(userInfo);
return userInfo.userName;
})
.catch(this.handleError);
When I looked at the request using Fiddler, I noticed that when I send request using Angular 4, Content-type header is not set to multipart/form-data (and when I use Postman it is). I've tried setting it, but it was set to application/json again.
I've also tried without [FromForm], but also no luck. I'm not sure what to do next.

sending form data with file and boolean values in angular2

I have a form where the user selects from a set of check boxes and also selects a picture. I'm sending this form from an angular2 front-end to an asp.net core web api backend. The issue i am having is that when i send the data, only the image file is sent, all the check box data which is in boolean is ignored. It's my first time doing this so i'm not sure how to handle it.
Below is the code i am using for adding the data to a form data
var formData = new FormData();
formData.append('ReturnFaceLandMarks', this.formViewModel.ReturnFaceLandmarks);
formData.append('ReturnFaceId', this.formViewModel.ReturnFaceId);
formData.append('age', this.formViewModel.age);
formData.append('facial_hair', this.formViewModel.facial_hair);
formData.append('gender', this.formViewModel.gender);
formData.append('glassed', this.formViewModel.glassed);
formData.append('head_pose',"false");
formData.append('smile', "true");
formData.append('file', this.formViewModel.img);
and down here is the post request
detect(data: any): Promise<any>
{
return this.http.post(this.serverUrl+"face/detect/", data, { headers: this.headers })
.toPromise()
.then(response => {
console.log(response);
})
.catch(this.handleError);
}
The file gets sent to my web api, but the only file i see there is the image file.Below is my request payload.
I ran into similar issues working with Angular and .Net
The solution that worked best for me was to either create a class (model) that the FormData mapped to or to specify the web api controller method parameters with the [FromForm] attribute.
public IActionResult Upload(IFormFile file, [FromForm] bool smile) {
...
}

Asp.net Web API: HttpClient Download large files breaks

I have a web service (made in Asp.net Web API) that returns an xml file of about 10MB size.
The service has been tested with Fiddler and it is working
I am trying to download the file using HttpClient class. The problem is that the compilator never gets outside the await client.GetAsync() method, even if the API project returned the HttpResponseMessage.
This is my function
public async Task<XDocument> DownloadXmlAsync(string xmlFileName)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:51734/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
// When the copiler enters this next command, it doesn't get outside anymore
HttpResponseMessage response = await client.GetAsync("api/applications/ApplicationXml?fileName=" + xmlFileName);
response.EnsureSuccessStatusCode();
string stringResponse = await response.Content.ReadAsStringAsync();
XDocument xDoc = new XDocument(stringResponse);
return xDoc;
}
}
I updated also the maxRequestLength in web.config
<httpRuntime maxRequestLength="15360" />
What i am doing wrong?
Edit
Calling the function
public async Task<ActionResult> Index()
{
var xmlTask = DownloadXmlAsync("1.xml");
// doesn't reach here
var result = xmlTask.Result;
return View();
}
You're causing a classic deadlock by calling Result. Instead, you should await the task:
public async Task<ActionResult> Index()
{
var xmlTask = DownloadXmlAsync("1.xml");
// doesn't reach here
var result = await xmlTask;
return View();
}
I explain this deadlock in full on my blog, but the general idea is like this:
ASP.NET only allows one thread to be processing a request at a time.
When you await a Task, the compiler will capture a "context" and use it to resume the method when the Task completes. In the case of ASP.NET, this "context" is a request context.
So when DownloadXmlAsync (asynchronously) waits for GetAsync to complete, it returns an incomplete task to Index.
Index synchronously blocks on that task. This means the request thread is blocked until that task completes.
When the file is received, GetAsync completes. However, DownloadXmlAsync cannot continue because it's trying to resume that "context", and the "context" already has a thread in it: the one blocked on the task.
Hence, deadlock.

Resources