Reactjs Axios File upload - reactjs

I am trying to upload file to my .net core backend, file successfully uploads when i use postman or the swagger ui buh when i try using axios it keeps returning
request failed with status code 400
Here is my reactjs code snippet
const formData = new FormData();
formData.append("image", payload.img,);
formData.append("name", payload.name);
var config = {
headers: {
Authorization: `Bearer ${payload.token}`,
"content-type": "multipart/form-data",
},
};
let res = await axios.post(`${BASE_URL}/merchant/logo`, formData, config);
Please i have tried everything it seems not to be working I don't know what to do.
Here is my model class
public class Logo
{
public string name{ get; set; }
public IFormFile image{ get; set; }
}
here is my .Net core Action
var logoName = merchant.Identifier + "." + logoDto.Image.FileName.Split(".")[1];
string oldPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/logo", merchant.Logo);
string path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/logo", logoName);
if (File.Exists(oldPath)) File.Delete(oldPath);
using (Stream stream = new FileStream(path, FileMode.Create))
{
await logoDto.Image.CopyToAsync(stream);
}

It is still not clear, but I want to share the corret method to realize it.
Ensure payload.img is a single file.
IF you use [ApiController], it needs to be formulated [FromForm].
[ApiController]
[Route("[controller]")]
public class ValController:Controller
{
[HttpPost("get")]
public IActionResult get([FromForm]Logo logo)
{
return Ok();
}
}

Related

No 'Access-Control-Allow-Origin' header is present on the requested resource. When using ajax

I have REST API which I wrote on Spring Boot.
I want to write a frontend for it using React. To begin with, I decided to make sure that my frontend correctly receives data from the API.
Here is my rest controller code:
#RestController
#RequestMapping("/api/restaurants")
public class RestaurantRestController {
private final RestaurantService restaurantService;
public RestaurantRestController(RestaurantService restaurantService) {
this.restaurantService = restaurantService;
}
#GetMapping
// #PreAuthorize("hasAuthority('everything:read entries')")
#ApiOperation("Get all restaurants")
public ResponseEntity<List<RestaurantDto>> getAll() {
List<RestaurantDto> result = restaurantService.findAll().stream()
.map(RestaurantDto::fromRestaurant)
.collect(Collectors.toList());
return new ResponseEntity<>(result, HttpStatus.OK);
}
I wrote a configuration class on the backend side:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000/")
.allowedMethods("GET", "POST, "PUT", "DELETE")
.allowCredentials(true).maxAge(3600);
}
}
And I access my controller from the frontend with this method:
import axios from 'axios';
const REST_URL = "http://localhost:8080/api/restaurants";
export default class RestaurantsAPI {
static async getAll() {
const response = await axios.get(REST_URL);
return response.data
}
}
And I get the correct answer.
Then I add credentials to my request:
import axios from 'axios';
const REST_URL = "http://localhost:8080/api/restaurants";
export default class RestaurantsAPI {
static async getAll() {
const response = await axios.get(REST_URL, {
auth: {
username: 'admin', password: 'admin'
}
});
return response.data
}
}
Now I see this in the console:
enter image description here
At the same time, it doesn’t matter, I leave access to the method open to everyone, using this configuration:
.antMatchers(HttpMethod.GET, "/api/restaurants").permitAll()
Or vice versa, I comment this configuration and apply an annotation to the method:
#PreAuthorize("hasAuthority('everything:read entries')")
I still get the same error.
Thanks to Postman and JUnit Tests, I know that Spring Security is configured and working properly.
Please explain what is the reason for this behavior and what should I do to fix it. Thank you.

How to consume a spring boot api containing #CurrentUser annotation with react?

I'm trying to consume a Spring-Boot API using React.
It worked fine on the server side and lately I had to add #CurrentUser UserPrincipal userPrincipal as a parameter and it's still working fine.
The problem is when trying to send Http requests it starts giving me a NullPointerException and I expected that because I didn't add anything inside the react function.
What must I add in the frontend?
Backend:
#CrossOrigin(origins = "*", maxAge = 3600)
#PostMapping("/FileUpload")
public void fileUpload(#RequestParam("file") MultipartFile file, #CurrentUser UserPrincipal userPrincipal,
Patient patient, Observation observation) {
String result = hl7v22cs.fileParser(file);
if (result.contains("|2.2")) {
hl7v22cs.fileParser(file);
hl7v22cs.textParser(file);
hl7v22cs.extractPatientSegment(userPrincipal, patient, file);
hl7v22cs.extractObservationSegment(observation, file);
}
}
Frontend:
class ConverterService {
convert(file) {
let formData = new FormData();
formData.append("file", file);
return axios.post("http://localhost:8080/api/FileUpload", formData, {
headers: {
"Content-Type": "multipart/form-data",
}
});
}
}

Call .NET Core API from AngularJS using $https - 400 Bad Request

I'm trying to call a .NET Core API from AngularJS. In the AngularJS I'm calling the method like this:
$http({
method: 'POST',
url: '/api/message/transaction/' + this.transaction.id,
data: { "transactionJson": "hello"}
})
.then(function (response) {
var r = response;
})
My .NET Core API method is like this:
[Route("~/api/message/transaction/{transactionId}")]
[HttpPost]
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] string transactionJson)
{
I'm getting a 400 Bad Request response back from the server. How do I fix it?
I realised the type for the parameter must be a type that has a property named TransactionJson, so I need to define a new C# type:
public class TransactionData() {
public string TransactionJson
}
Then in the API method:
[Route("~/api/message/transaction/{transactionId}")]
[HttpPost]
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] TransactionData transactionJson)
{
getting a 400 Bad Request response back from the server. How do I fix it?
To fix the issue, as your mentioned, one solution is modifying action parameter, like below.
public async Task<ActionResult<DeviceEventsTransactionmsg>> PostTransaction([FromBody] TransactionData transactionJson)
{
//...
//code logic here
TransactionData class
public class TransactionData
{
public string TransactionJson { get; set; }
}
Besides, we can also implement and use a custom plain text input formatter to make PostTransaction action method that accepts a string-type ACTION parameter work well.
public class TextPlainInputFormatter : TextInputFormatter
{
public TextPlainInputFormatter()
{
SupportedMediaTypes.Add("text/plain");
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
string data = null;
using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
{
data = await streamReader.ReadToEndAsync();
}
return InputFormatterResult.Success(data);
}
}
Add custom formatter support
services.AddControllers(opt => opt.InputFormatters.Insert(0, new TextPlainInputFormatter()));
Test Result

File upload using react + asp.net core 2 application not working

I am trying to do a file upload functionality, where my front end contains react and server is asp.net core 2. I tried with various combinations but my code is not working.(Getting error at server end and most likely getting content-type error). Following is the snippets for both front end and server:
React Code is:
const formData: any = new FormData();<br />
formData.append("File",data[0]); // data[0] contains the file object<br/>
return axios.post(SAVE_ATTACHMENT_DATA, formData,
{headers: { 'Content-Type':'multipart/form-data' }}
)
.then(resp => {
//
}, err => {
//
})
};
ASP.NET Core 2 Code is:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload()
{
var files = Request.Form.Files; // getting error here in "Form"
FileUploadViewModel model = new FileUploadViewModel(); // model been defined in another file
var file = model.File;
if (file.Length > 0)
{
string path = Path.Combine(#"temp\", "uploadFiles");
using (var fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fs);
}
model.source = $"/uploadFiles{file.FileName}";
model.Extension = Path.GetExtension(file.FileName).Substring(1);
}
return BadRequest();
}
Can some one please help me with the same.
It should work like this:
React Code
const formData = new FormData();
formData.append("file", data[0]);
return axios.post(SAVE_ATTACHMENT_DATA, formData)
ASP.NET Core 2:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file.Length > 0)
{
string path = Path.Combine(#"temp\", "uploadFiles");
using (var fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fs);
}
model.source = $"/uploadFiles{file.FileName}";
model.Extension = Path.GetExtension(file.FileName).Substring(1);
}
return BadRequest();
}
Important: The name of the file in React has to be the same as the parameter name in the .NET Core method or else the IFormFile will be null. For example formData.append('sameName', data[0]); in React and IFormFile sameName in .NET Core.
All you're doing in your action is newing up your model, which then, obviously isn't going to have any file uploads associated with it, because it was created manually by you and not from the post data. Instead, you should take your model as a param to your action, and then use that instance rather than creating your own:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload(FileUploadViewModel model)

Not able to access web api calls in a api/controller format

Hi I am developing one application using web api2 and accessing calls via angularjs. I created web api calls and hosted in iis server(public ip). I am accessing the web api2 methods in the below format.
$http.post('http://111.93.133.98:4500/api/NCT_Login/', credentials).success(function (response) { alert(response); });
This is my web api config.cs file.
routeTemplate: "api/{controller}/{id}"
This is my controller code.
public class NCT_LoginController : ApiController
{
public NCTEntities entityObject = new NCTEntities();
[EnableCors(origins: "*", headers: "*", methods: "GET, POST, PUT, DELETE")]
public IHttpActionResult Post(LoginClass obj)
{
try
{
if (ModelState.IsValid)
{
obj.User_Password = PasswordEncryption.sha256_hash(obj.User_Password);
bool result = (from c in entityObject.NCT_UserRegistration where obj.User_Name ==c.User_Name && obj.User_Password == c.User_Password select c).Any();
if(result==true)
{
obj.UserRole = (from c in entityObject.NCT_UserRegistration where obj.User_Name == c.User_Name && obj.User_Password == c.User_Password select c.User_Role).FirstOrDefault();
obj.Success = 0;
obj.User_Password = "";
var response = Request.CreateResponse(HttpStatusCode.OK, obj);
var newSessionId = new SessionIDManager().CreateSessionID(HttpContext.Current);
var cookie = new CookieHeaderValue("session-id", newSessionId);
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
response.Headers.AddCookies(new[] { cookie });
return ResponseMessage(response);
}
else
{
return Content(HttpStatusCode.BadRequest, 1);
}
}
else
{
return Content(HttpStatusCode.BadRequest, 1);
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
If i remove api from route template I am able to access api's and if i put api.NCT_Login then I am getting preflight error. I am not sure what i am missing here. Any help would be appreciated. Thank you.
I would decorate the post method with a attribute route like this
[RoutePrefix("api/NCT_Login")]
public class NCT_LoginController : ApiController
{
public NCTEntities entityObject = new NCTEntities();
[EnableCors(origins: "*", headers: "*", methods: "GET, POST, PUT, DELETE")]
[Route("Login")]
[HttpPost]
public IHttpActionResult Post(LoginClass obj)
{
This would set the route to api/NCT_Login/Login
IMO its a good practice to use attribute routing as it gets very clear what each method route is.
Also when controllers grow its easy to define new routes on the same http verb

Resources