I am using ASP.NET Core Razor pages in .NET 8 and VS2022.
I am trying to keep my controllers hidden from the public, so all my POST
requests first call the same page. Eg www.mywebsite.com/index
will call the ASP.NET Core event handler for the index page.
SCENARIO 1
When I try to upload via Ajax post (if I call a controller with the anti forgery token, it works), it hits the controller action. But fails with the Razor page, event handler of the same page
SCENARIO 2
When I try to upload to the same index page, I get bad request. Here is my code. I have tried using IActionResult
and adding an ImageUpload
class (which is commented out below), both of which produce the same result: BAD REQUEST
//public async Task<IActionResult> OnPostAsync(ImageUpload imageUpload)
public async Task OnPostAsync()
{
var file = Request.Form.Files[0];
var fileName = Path.GetFileName(file.FileName);
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
//return Content($"File '{fileName}' uploaded successfully.");
}
Here is my frontend code. I have tried using examples I seen online, by JSON.Stringfy, which also does not work:
$('#fileInput').change(function () {
var token = $('#__RequestVerificationToken').val();
var file = this.files[0];
if (file) {
var reader = new FileReader();
var formData = new FormData();
formData.append('file', file);
reader.onload = function (e) {
$('#previewImage').attr('src', e.target.result).show();
var formData = new FormData();
formData.append('file', file);
var formData2 = JSON.stringify(formData);
$.ajax({
type: "POST",
url: "",//this enables it to post to the root
contentType: "application/json",
processData: false,
data: formData2,
headers: {
RequestVerificationToken: token
},
success: function (response) {
console.log('File uploaded successfully');
},
error: function (xhr, status, error) {
console.error('Error uploading file:', error);
}
});
};
}
});
And finally, this is my HTML:
<form>
@Html.AntiForgeryToken()
<p>
<input type="file" id="fileInput" accept="image/*">
<br><br>
<img src="" id="previewImage" style="max-width: 300px; max-height: 300px; display: none;">
</p>
</form>
The most common cause for a 400 Bad Request status code in Razor Pages is a missing Request Verification token.
You can use F12
to see the token value in the source tab, set a breakpoint at var token = $('#__RequestVerificationToken').val();
it show :
change it to:
var token = $('input:hidden[name="__RequestVerificationToken"]').val();
Try the code like:
$('#fileInput').change(function () {
var token = $('input:hidden[name="__RequestVerificationToken"]').val();
var file = this.files[0];
if (file) {
var reader = new FileReader();
var formData = new FormData();
formData.append('file', file);
reader.onload = function (e) {
$('#previewImage').attr('src', e.target.result).show();
var formData = new FormData();
formData.append('file', file);
}
}
$.ajax({
type: "POST",
url: "/Index",//this enables it to post to the root
processData: false,
contentType: false,
data: formData,
headers: {
RequestVerificationToken: token
},
success: function (response) {
console.log('File uploaded successfully');
},
error: function (xhr, status, error) {
console.error('Error uploading file:', error);
}
});
});
result: