Posting data and file with Aurelia to ASP.NET webapi - javascript

I'm trying to add an input with file upload to my application.
This is my view with two inputs, one text and one file:
<template>
<form class="form-horizontal" submit.delegate="doImport()">
<div class="form-group">
<label for="inputLangName" class="col-sm-2 control-label">Language key</label>
<div class="col-sm-10">
<input type="text" value.bind="languageKey" class="form-control" id="inputLangName" placeholder="Language key">
</div>
</div>
<div class="form-group">
<label for="inputFile" class="col-sm-2 control-label">Upload file</label>
<div class="col-sm-10">
<input type="file" class="form-control" id="inputFile" accept=".xlsx" files.bind="files">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Do import</button>
</div>
</div>
</form>
</template>
In my webapi I have this code which I copied and pasted from here:
public class ImportLanguageController : ApiController
{
public async Task<HttpResponseMessage> Post()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
//Trace.WriteLine(file.Headers.ContentDisposition.FileName);
//Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
At last I have my view model in Aurelia:
import {inject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
#inject(HttpClient)
export class Import {
languageKey = null;
files = null;
constructor(http){
http.configure(config => {
config
.useStandardConfiguration();
});
this.http = http;
}
doImport() {
//What goes here??
}
}
So my question is, what logic goes in my function doImport? I'm not sure the code in my controller method in the webapi is correct, feel free to have comments on that.

This should help you get started:
doImport() {
var form = new FormData()
form.append('language', this.languageKey)
form.append('file', this.files)
//Edit, try this if the first line dont work for you
//form.append('file', this.files[0])
this.http.fetch('YOUR_URL', {
method: 'post',
body: form
})
.then( response => {
// do whatever here
});
}
Depending on the webapi response you provide (if any) you may want to use following:
.then( response => response.json() )
.then( response => {
// do whatever here
});
One thing I should mention too is that fetch uses COR so if you get any CORS error you may need to enable them on the server side.
Here's a gist.run for the Aurelia part (posting won't work unless you change the URL):
https://gist.run/?id=6aa96b19bb75f727271fb061a260f945

Related

How to get data from url into post request?

Any help appreciated. I've got an app that pulls data from google books api. From each book page, the user is able to leave a review. The path to the review is /review/${isbn Number}. Each page has a path based on the isbn. The review routes work and I'm able to make the post request through insomnia/postman with no issues, I'm just having trouble with the front-end js in pulling the data from the input boxes to make the post request. I'm not sure if the issue is because the isbn being in the path. Below is my front-end javascript that I am unable to fix.
const newFormHandler = async (event) => {
event.preventDefault();
console.log("testing")
const description = document.querySelector('#description').value;
const reviewTitle = document.querySelector('#reviewTitle').value;
const isbn = window.location.search
if (description) {
const response = await fetch(`api/review/${isbn}`, {
method: 'POST',
body: JSON.stringify({ description, reviewTitle }),
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
document.location.reload();
} else {
alert('Failed to create review');
}
}
};
document
.querySelector('.form-group')
.addEventListener('submit', newFormHandler);
My form is below:
<div class="col form-group">
<div class ="card reviewCard" style = "background-color:#fcf8f3; color: #65625e;">
<form id="blog-form">
<div>
<label for="reviewTitle">Review Title</label>
<input
value="{{title}}"
id="reviewTitle"
name="reviewtitle"
placeholder="Enter Review Title"
type="text"
required="required"
class="form-control"
data-bv-notempty="true"
data-bv-notempty-message="The title cannot be empty"
/>
</div>
<div>
<label for="review">Review</label>
<textarea
id="description"
name="review"
cols="40"
rows="10"
required="required"
class="form-control"
>{{description}}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
And here is my route that works fine with insomnia, no issues.
router.get('/review/:id', async (req, res) => {
try {
const isbn13 = req.params['id'];
const reviewData = await Review.findAll({ where: {
isbn:isbn13
},
include: [
{
model: User,
attributes: ['name'],
}
]
})
const reviews = reviewData.map((review) => review.get({ plain:true}));
// console.log(isbn13);
res.render('review', {
isbn: isbn13, reviews:reviews
});
} catch (err) {
console.log(err)
}
});
Any help appreciated. I tried to pull in the isbn number from the path, but with no success. I think I have it formatted wrong somehow.
First console log your req
You should see the body containing some data.
In a get request the they are arguments in the URL.
In a Psot request they are in the body of the request.

Can't figure out how to make a function for creating new users into the database

I am new to working with databases. I've been trying to create a login/register webpage using only HTML, Js and MongoDB in my codes in order to practice. I have successfully made a function for login, yet I've been struggling to create a function for registering using the Fetch API.
I am aware that my register code is used rather for a login function, but I used it as a template for the sign up one.
I'd appreciate it if anyone can help me fix the register function using Fetch() in order to not give me 401 and to be able to add the new user's email and password to my database. Thank you.
const btnAccount = document.querySelector('.account .submit')
btnAccount.addEventListener('click', event => {
event.preventDefault()
const email = emailAccount.value
const pass = passAccount.value
const pass2 = pass2Account.value
if (email && pass && pass2) {
if (pass === pass2) {
// The data i wish to add to my mongoDB users database:
const account = {
strategy: "local",
email : emailAccount.value,
password: passAccount.value
}
fetch('http://localhost:3030/authentication', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(account)
}).then(response => {
return response.json()
}).then(result => {
console.log(result)
document.forms[1].reset();
})
.catch(err => {
// If I got some errors regardings the DB or in the code itself:
console.log('eroare:', err)
alert(`Something's wrong. I can feel it!`)
})
}
else {
// Passwords not the same:
alert('Parolele nu coincid!')
}
}
else {
// Not all fields written:
alert('Completeaza bah campurile...')
}
})
<main>
<form class="account">
<div>
<label for="email">Email:</label>
<input required type="email">
</div>
<div>
<label for="password">Password:</label>
<input required type="password" class="password">
</div>
<div>
<label for="password2">Verify Password:</label>
<input type="password" class="password2">
</div>
<div>
<button class="submit">Create new account</button>
</div>
<div>
I already have an account
</div>
</form>
<button class="fetchItems">Load ITEMS</button>
<div class="output"></div>
</main>

How to make a post request to a protected Laravel API route with JavaScript using the API token?

Description
I have a table, where i collect values from checkboxes with JavaScript. This values should be send to a protected API route in a Laravel backend.
I use the standard Laravel auth setup (out of the box).
Question
What do I have to send with the JavaScript post request for authentication and how do i do that? Can i add a auth token or something like that to the headers?
At the moment i get the reponse:
"This action is unauthorized".
exception: "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"
Edit
At the current point of my research the api token seems to be a simple solution for my case. But i can't figure out how to attach the api token to the JavaScript post request.
Thats the JavaScript function for collecting the values storing them in objects.
import SaveData from "../api/SaveData";
export default async function SaveMultipleReports() {
const table = document.getElementById("reports-dashboard");
const rows = table.querySelectorAll("div[class=report-tr]");
let reports = [];
for (const row of rows) {
const checkbox_visible = row.querySelector("input[name=visible]")
.checked;
const checkbox_slider = document.querySelector(
"input[name=show_in_slider]"
).checked;
const report = {
id: row.id,
visible: checkbox_visible,
show_in_slider: checkbox_slider
};
reports.push(report);
}
console.log(reports);
const response = await SaveData("/api/reports/update", reports);
console.log(response);
}
And that is the SavaData function:
export default async function SaveData(api, data) {
const token = document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content");
const url = window.location.origin + api;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": token,
Accept: "application/json"
},
body: JSON.stringify(data)
});
const result = await response.json();
return result;
}
And thats the line in the api.php:
Route::middleware("can:administration")->post("reports/update", "ReportsController#UpdateAll");
The whole repo is here.
Thanks for your time in advance :)
Edit 2
For now i managed it without JavaScript. Put all the values, i want to update in form and load a hidden input for the ID of every object (the ID is needed for the controller afterwards).
Thanks to this post.
{!! Form::open(["route" => ["admin.reports.multiupdate"], "method" => "PUT", "class" => "report-table"]) !!}
... // some HTML
#foreach ($reports as $report)
<div class="report-tr">
<input type="hidden" name="reports[{{$loop->index}}][id]" value="{{$report->id}}">
<div class="td-name">
<p class="td-text">{{$report->name}}</p>
</div>
<div class="td-flex">{{$report->body}}</div>
<div class="tr-wrapper">
<div class="checkbox-visible">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][visible]" value="1" checked>
<span class="checkmark"></span>
</div>
<label class="table-label" for="visible">Sichtbar</label>
</div>
<div class="checkbox-slider">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][show_in_slider]" value="1"
{{($report->show_in_slider == 1 ? "checked" : "")}}>
<span class="checkmark"></span>
</div>
<label class="table-label" for="show_in_slider">Im Slider</label>
</div>
<div class="td-buttons">
...
#endforeach
<button class="floating-save">
#svg("saveAll", "saveAll")
</button>
{!! Form::close() !!}
And a snippet from the Controller:
public function MultipleUpate(ReportUpdate $request)
{
$reports = $request->input("reports");
foreach ($reports as $row) {
$report = Report::find($row["id"]);
// giving the checkbox 0, if it isn't checked
$isVisible = isset($row["visible"]) ? 1 : 0;
$inSlider = isset($row["show_in_slider"]) ? 1 : 0;
$report->visible = $isVisible;
$report->show_in_slider = $inSlider;
$report->new = false;
if ($report->save()) {
$saved = true;
}
}
if ($saved == true) {
$request->session()->flash("success", "Ă„nderungen gespeichert!");
} else {
$request->session()->flash("error", "Das hat nicht geklappt!");
}
return back();
The ReportUdpate function contains only that:
public function authorize()
{
return true;
}
public function rules()
{
return [
"visible" => "nullable",
"show_in_slider" => "nullable"
];
}
You are talking about authentication but using an authorization middleware. There is a difference between the two.
Read about it here: https://medium.com/datadriveninvestor/authentication-vs-authorization-716fea914d55
With that being said, what you are looking for is an authentication middleware that protects your routes from unauthenticated users. Laravel provides a middleware called Authenticate out of the box for this specific purpose.
Change your route to be like so:
Route::middleware("auth")->post("reports/update", "ReportsController#UpdateAll");

Using post from Angular.js does not work

Ive built a rest-API to add todos in a mongodb. I can successfully save instances by using the following setup in postman:
http://localhost:3000/api/addtodo x-www-form-urlencoded with values text="Test", completed: "false".
Now when I try to replicate this with Angular, it doesnt work, the todo is saved but without the text and completed attributes, I cant seem to access the text or completed values from body. What am I doing wrong? Code below:
Angular-HTML:
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
<input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
</div>
<!-- createToDo() WILL CREATE NEW TODOS -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
Angular-js:
$scope.createTodo = function() {
$http.post('/api//addtodo', $scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
REST-API:
router.post('/addtodo', function(req,res) {
var Todo = require('../models/Todo.js');
var todo = new Todo();
todo.text = req.body.text;
todo.completed = req.body.completed;
todo.save(function (err) {
if(!err) {
return console.log("created");
} else {
return console.log(err);
}
});
return res.send(todo);
});
$http.post sends it's data using application/json and not application/x-www-form-urlencoded. Source.
If you're using body-parser, make sure you've included the JSON middleware.
app.use(bodyParser.json());
Either that or change your default headers for angular.
module.run(function($http) {
$http.defaults.headers.post = 'application/x-www-form-urlencoded';
});

How to send data in json format in jquery ajax for restfull web services

I am sending the json format data in jquery ajax for restful web services but It is not sending. I am new in web technology, so please help me. I write the script for sending the JSON data using following link
how to pass JSON data to restful web services through ajax and also how to get JSON data?
My javascript code is
<script type="text/javascript">
$(document).ready(function(){
$('#btnBooking').click(function(){
var serviceCategory=document.getElementById("services").value;
var availDate=document.getElementById("scheduledDate").value;
var custName=document.getElementById("userName").value;
var custMobile=document.getElementById("userContactNumber").value;
var custEmail=document.getElementById("addressemailId").value;
var custAddress=document.getElementById("address1").value;
var JSONObject= {"serviceCategory":serviceCategory, "availDate":availDate, "custName":custName, "custMobile":custMobile, "custEmail":custEmail, "custAddress":custAddress};
var jsonData = JSON.stringify( JSONObject );
$.ajax({
url: "http://localhost:8080/HomeServiceProvider/rest/booking/saveBookingDetails",
type: "POST",
dataType: "json",
data: jsonData,
contentType: "application/json",
success: function(response){
alert(JSON.stringify(response));
},
error: function(err){
alert(JSON.stringify(err));
}
});
});
});
</script>
My Html code is
<form class="form-horizontal" id="scheduleLaterForm" name="scheduleLaterForm" action="#" method="post">
<div class="col-lg-8">
<div class="alert alert-danger alert-dismissable" style="display: none;" id="errorMessageDiv">Error
Message Goes Here</div>
<div class="form-group">
<label class="col-lg-3 control-label">Name:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" id="userName" name="userName" placeholder="Full Name" value="" type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Services:</label>
<div class="col-lg-9">
<select class="form-control" id="services" name="subService">
<option>Select Service</option>
<option value="1">Carpenter</option>
<option value="2">Mobile SIM services</option>
</select>
</div>
</div>
<div class="form-group">
<label for="schedule-tme" class="col-lg-3 control-label">Schedule Date:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<div class="input-group date form_datetime" data-date="dd-M-yyyy">
<input placeholder="Choose Date" class="form-control" value="" onchange="timeValidate()" id="scheduledDate" name="scheduledDate" readonly="readonly" type="text"> <span class="input-group-addon"> <span class="glyphicon glyphicon-th calender-click"></span></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Address:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" name="address1" id="address1" placeholder="Full address" value="" type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">City:</label>
<div class="col-lg-9">
<input class="form-control" id="" value="Bangalore" name="" placeholder="City Name" readonly="readonly" type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Mobile:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" id="userContactNumber" name="userContactNumber" placeholder="Mobile Number" onkeypress="enableKeys(event);" maxlength="10" type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Email:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" name="addressemailId" id="addressemailId" placeholder="you#example.com" value="" type="text">
</div>
</div>
<div class="form-group marg-bot-45">
<label class="col-lg-3 control-label"></label>
<div class="col-lg-9">
Confirm Booking <span class="glyphicon glyphicon-ok"></span>
</div>
</div>
</div>
</form>
Booking.java
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* Booking generated by hbm2java
*/
#Entity
#Table(name = "booking", catalog = "service4homes")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Booking implements java.io.Serializable {
private Integer BId;
private ServiceProviderStatus serviceProviderStatus;
private ServiceCategory serviceCategory;
private Date availDate;
private String custName;
private String custMobile;
private String custEmail;
private String custAddress;
private Set<Allocation> allocations = new HashSet<Allocation>(0);
private Set<SuperAdmin> superAdmins = new HashSet<SuperAdmin>(0);
public Booking() {
}
public Booking(ServiceProviderStatus serviceProviderStatus,
Customer customer, ServiceCategory serviceCategory, Date availDate,
String custEmail) {
this.serviceProviderStatus = serviceProviderStatus;
this.serviceCategory = serviceCategory;
this.availDate = availDate;
this.custEmail = custEmail;
}
public Booking(ServiceProviderStatus serviceProviderStatus,
Customer customer, ServiceCategory serviceCategory, Date availDate,
String custName, String custMobile, String custEmail,
String custAddress, Set<Allocation> allocations,
Set<SuperAdmin> superAdmins) {
this.serviceProviderStatus = serviceProviderStatus;
this.serviceCategory = serviceCategory;
this.availDate = availDate;
this.custName = custName;
this.custMobile = custMobile;
this.custEmail = custEmail;
this.custAddress = custAddress;
this.allocations = allocations;
this.superAdmins = superAdmins;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "b_id", unique = true, nullable = false)
public Integer getBId() {
return this.BId;
}
public void setBId(Integer BId) {
this.BId = BId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "sps_id", nullable = false)
#JsonIgnore
public ServiceProviderStatus getServiceProviderStatus() {
return this.serviceProviderStatus;
}
public void setServiceProviderStatus(
ServiceProviderStatus serviceProviderStatus) {
this.serviceProviderStatus = serviceProviderStatus;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "sc_id", nullable = false)
#JsonIgnore
public ServiceCategory getServiceCategory() {
return this.serviceCategory;
}
public void setServiceCategory(ServiceCategory serviceCategory) {
this.serviceCategory = serviceCategory;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "avail_date", nullable = false, length = 19)
public Date getAvailDate() {
return this.availDate;
}
public void setAvailDate(Date availDate) {
this.availDate = availDate;
}
#Column(name = "cust_name", length = 50)
public String getCustName() {
return this.custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
#Column(name = "cust_mobile", length = 13)
public String getCustMobile() {
return this.custMobile;
}
public void setCustMobile(String custMobile) {
this.custMobile = custMobile;
}
#Column(name = "cust_email", nullable = false, length = 50)
public String getCustEmail() {
return this.custEmail;
}
public void setCustEmail(String custEmail) {
this.custEmail = custEmail;
}
#Column(name = "cust_address", length = 100)
public String getCustAddress() {
return this.custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "booking")
public Set<Allocation> getAllocations() {
return this.allocations;
}
public void setAllocations(Set<Allocation> allocations) {
this.allocations = allocations;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "booking")
#JsonIgnore
public Set<SuperAdmin> getSuperAdmins() {
return this.superAdmins;
}
public void setSuperAdmins(Set<SuperAdmin> superAdmins) {
this.superAdmins = superAdmins;
}
}
I think you will have to add contentType also to the ajax request call,because you are trying to send json format data to server,like below.
var request = $.ajax({
url: "http://localhost:8080/HomeServiceProvider/rest/booking/saveBookingDetails",
type: "POST",
data: jsonData,
contentType: "application/json",
dataType: "json"
});
dataType : data format, you are expecting form server
contentType : data format ,you are sending to server
Are you sure its not working ? I copied the same code as yours and tried executing on my domain and its just fine. here is the code, I replaced the variables with some hardcoded numbers.
var jsonData = JSON.stringify({"serviceCategory": 4, "availDate":2, "custName":4, "custMobile":4, "custEmail":4, "custAddress":4});
$.ajax({
url: "http://cloudpanel.abstractdns.com",
type: "POST",
dataType: "json",
data: jsonData,
contentType: "application/json",
success: function(response){
alert(JSON.stringify(response));
},
error: function(err){
alert(JSON.stringify(err));
}
});
And here is the screenshot from firefox console that shows JSON data was sent properly.
The screenshot above clearly says its sending the correct data in the format specified. And if its not working can paste the screenshot from firebug so we can understand if its really not working, I'm saying this as you have already told that your new to web technologies. In case you don't know, you can install firebug on mozilla and chrome and do the inspecting yourself that will give you the insights of errors in any.
With respect to your comment, you have stated that you get an error regarding CORS. So this could be solved by replacing dataType: json with dataType: "jsonp". That should solve your problem if your app that has ajax and the app that ajax sends requests are on different servers.
Hope that helps
You have mixed up JSON.parse() and JSON.stringify()
JSON.parse():
The JSON.parse() method parses a string as JSON, optionally transforming the value produced by parsing.
JSON.stringify():
The JSON.stringify() method converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is specified, or optionally including only the specified properties if a replacer array is specified.
So in your code, you have to change JSON.parse to JSON.stringify
You have to send a string which is Json data. So convert your javascript object "JSONObject" with JSON.stringify
var JSONObject= ...;
var jsonData = JSON.stringify( JSONObject );
Here you can find an example how u can extend jquery to have a postJSON function if you need this functionality more often.

Categories