404 on webapi custom route - reactjs

I am really struggling with this
I have an action controller like this:
[HttpPost]
[Route("api/SiteCollections/SetSiteCollectionActive")]
public async Task<IHttpActionResult> SetSiteCollectionActive(string siteCollectionUrl)
{
var siteCollectionsStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
var allSiteCollections = await siteCollectionsStore.Query().Where(x => x.Title != null).ToListAsync();
foreach (TenantManagementWebApi.Entities.SiteCollection sc in allSiteCollections)
{
sc.Active = false;
await siteCollectionsStore.UpdateAsync(sc);
}
var siteCollection = await siteCollectionsStore.Query().FirstOrDefaultAsync(x => x.Id == siteCollectionUrl);
if (siteCollection == null)
{
return NotFound();
}
siteCollection.Active = true;
var result = await siteCollectionsStore.UpdateAsync(siteCollection);
return Ok(result);
}
and from a reactjs application, I am trying to do the following:
// rowSelection object indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
if(selectedRows[0].Url != undefined){
console.log(selectedRows[0].Url);
const options = {
method: 'post'
};
adalApiFetch(fetch, "/SiteCollections/SetSiteCollectionActive?siteCollectionUrl="+selectedRows[0].Url.toString(), options)
.then(response =>{
if(response.status === 200){
Notification(
'success',
'Site Collection set to active',
''
);
}else{
throw "error";
}
})
.catch(error => {
Notification(
'error',
'Site Collection not activated',
error
);
console.error(error);
});
}
},
getCheckboxProps: record => ({
type: Radio
}),
};
return (
<Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
);
However, I always get this error:
everything seems correct
Route Config
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}

Related

How to set value to a state variable inside a function in react

I am getting a backend response to get the driver details using Axios and once after getting that I want to get the name, address of the driver. For that, I tried to set the value to a state variable but couldn't be able to assign, and also I have tried assigned the values to an array state variable and to access them later but I was unable to get a result
This is the code snippet:
getDriverInfo = async () => {
var session = sessionStorage.getItem("session");
var apiBaseUrl = "http://localhost:4000/api/";
// var self = this;
let det = [];
var payload = {
nic: session,
};
axios
.post(apiBaseUrl + "driverDetails", payload)
.then(async (response) => {
console.log(response.data.success);
if (response.data.code == 204) {
console.log("Driver Data retrieved successfull");
response.data.success.map((element) => {
det.push(element);
this.state.Ddetails.push(element);
});
console.log(det.length);
console.log(this.state.Ddetails[0].dln);
await this.setState({
fname: this.state.Ddetails[0].fName,
lname: this.state.Ddetails[0].lName,
});
} else {
console.log("Details does not exists");
alert("Details does not exist");
}
})
.catch(function (error) {
console.log(error);
});
console.log(det.length);
this.state.Ddetails.map((item) => {
console.log("Map");
console.log(item.dln);
});
console.log(this.state.Ddetails.dln);
};
Don't update state directly this is an anty pattern.
https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly
I have modified your code a little.
getDriverInfo = async () => {
var session = sessionStorage.getItem("session");
var apiBaseUrl = "http://localhost:4000/api/";
// var self = this;
let det = [];
var payload = {
nic: session,
};
axios
.post(apiBaseUrl + "driverDetails", payload)
.then(async (response) => {
console.log(response.data.success);
if (response.data.code == 204) {
console.log("Driver Data retrieved successfull");
response.data.success.map((element) => {
det.push(element);
//Don't use like this ==> this.state.Ddetails.push(element);
});
this.setState({Ddetails:det},()=>{
console.log(det.length);
console.log(this.state.Ddetails[0].dln);
this.setState(prevState=>{
console.log(det.length);
prevState.Ddetails.map((item) => {
console.log("Map");
console.log(item.dln);
});
console.log(prevState.Ddetails.dln);
return{
fname: prevState[0].fName,
lname: prevState[0].lName,
}
});
})
} else {
console.log("Details does not exists");
alert("Details does not exist");
}
})
.catch(function (error) {
console.log(error);
});
};
this.state = {
name: 'mickey',
lastName: 'mouse',
};
const display = () => {
// wont work
console.log(this.state.name, this.state.lastName);
}
function display() {
// will work
console.log(this.state.name, this.state.lastName);
}
As you can see arrow functions wont work with (this)

Unable to POST data in axios (React to SpringBoot) Formatted question in screenshot attached

In React component :
I am setting
const object = {
name: this.state.Name,
place: this.state.Place
}
callBackend(object).then(validateResult => {
if (validateResult.valid === true) {
this.setState({status: 'saved'});
} else {
this.setState({status: 'error'});
}
}
--------------
// this call goes to service
import axiosInstance from "../Axios";
export const callBackend = (object) =>
axiosInstance.post(`/employee/saveInfo`, { object }).then(res => {
console.log(res);
return res.data;
});
----------------
In java:
#PostMapping(path = "/saveInfo")
public ResponseEntity<List<object>> saveInfo(#RequestBody Object o) {
System.out.println(o.getName);// getting java.lang.NullPointerException
}
Solution is no brackets around object.
export const callBackend = (object) =>
axiosInstance.post(/employee/saveInfo, object).then(res => {
console.log(res);
return res.data;

React Function return nothing

I am trying to get Display Name getUserinfo() based on a User ID getList()
I have attempted
to use a variable to catch the data and feed to getList().
to use state variables to setState and pass data to getList(). but it seems State is asynchronous, so it failed
Problem: why my getUserinfo() cannot return a value for getList() to use ?
private getUserinfo(userid: number) {
var result;
let url;
url = `/_api/web/GetUserById(${userid})`;
const opt: ISPHttpClientOptions = {
headers: { "Content-Type": "application/json;odata=verbose" }
};
this.props.spHttpClient
.get(
this.props.context.pageContext.web.absoluteUrl + url,
SPHttpClient.configurations.v1,
opt
)
.then((response: SPHttpClientResponse) => {
response.json().then((json: any) => {
if (json.Title) {
let name = json.Title;
let email = json.Email;
let issiteadmin = json.IsSiteAdmin;
//debugger;
return name; // this has value but it returns nothing in another function I called
}
});
});
}
private getList() {
this.state.data.length = 0;
const qurl =
"/_api/web/lists/getbytitle('list')/items?$select=*&$orderby=Modified desc";
const opt: ISPHttpClientOptions = {
headers: { "Content-Type": "application/json;odata=verbose" }
};
this.props.spHttpClient
.get(
this.props.context.pageContext.web.absoluteUrl + qurl,
SPHttpClient.configurations.v1,
opt
)
.then((response: SPHttpClientResponse) => {
response.json().then((json: any) => {
for (let i = 0; i < json.value.length; i++) {
let authorid = json.value[i].AuthorId;
let editorid = json.value[i].Editorid;
let Authorname = this.getUserinfo(authorid);
let Editorname = this.getUserinfo(editorid);
debugger;
this.setState({
data: [
...this.state.data,
{
Authorname,
Editorname
}
]
});
}
});
});
}
Because you have not returned anything from getUserInfo, you had just called this.props.spHttpClient.get() without returning its value, for instance:
private getUserinfo(userid: number) {
...
return this.props.spHttpClient.get( ... )
.then((response: SPHttpClientResponse) => {
return response.json().then((json: any) => {
if (json.Title) {
let name = json.Title;
let email = json.Email;
let issiteadmin = json.IsSiteAdmin;
return name; // this has value but it returns nothing in another function I called
}
});
});
}
This way, when you call this.getUserinfo(authorid) you will get a promise and you can use its value as follows:
this.getUserinfo(authorid).then( name => {
// use its name
});
This is how you would write it using async/await which improves the readability
private async getUserinfo(userid: number) {
var result;
let url;
url = `/_api/web/GetUserById(${userid})`;
const opt: ISPHttpClientOptions = {
headers: { "Content-Type": "application/json;odata=verbose" }
};
const response: SPHttpClientResponse = await this.props.spHttpClient
.get(
this.props.context.pageContext.web.absoluteUrl + url,
SPHttpClient.configurations.v1,
opt
)
const json = await response.json();
if (json.Title) {
let name = json.Title;
let email = json.Email;
let issiteadmin = json.IsSiteAdmin;
//debugger;
return name; // this has value but it returns nothing in another function I called
}
}
You can aply the same style to getList

How to call get api in react js using ID?

I am trying to fetch customer record using ID but it gives me error 404 and even if I try using like "https://localhost:44387/api/Customers/5" in browser it gives result only for ID 5 and below error message for other id
{
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title":"Not Found",
"status":404,
"traceId":"|a1f6c563-4f8db349ec6c707f."
}
this is the call Customer. If I click on any edit it passes the ID but when It try to fetch the specific user data it gives me error. In onEditCustomer
import React from 'react';
import { Table, Button } from 'semantic-ui-react';
import AddCustomer from './AddCustomer';
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
formClose:false,
isAddCustomer:false,
isEditCustomer:false,
singleCustomer:{},
users: []
}
}
//fetch data
componentDidMount() {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers();
myHeader.append('Content-type', 'application/json');
myHeader.append('Accept', 'application/json');
myHeader.append('Origin','https://localhost:44387');
const options = {
method: 'GET',
myHeader
};
fetch(customerApi, options)
.then(res => res.json())
.then(
(result) => {
this.setState({
users: result,
isLoaded: true
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
//close form
closeForm = event => {
this.props.closeCreateForm();
}
//New Customer record
onAddFormSubmit = data => {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers({
'Accept':'application/json',
'Content-type':'application/json'
});
fetch(customerApi,{
method:'post',
headers:myHeader,
body:JSON.stringify(data)
})
.then(res => res.json())
.then(
(result) => {
console.log("Customer add result");
console.log(result);
this.setState({})
},(error) => {
this.setState({ error });
}
)
}
//Edit customer record
onEditCustomer = custId => {
const customerApi = 'https://localhost:44387/api/Customers/';
const customerRecord = new FormData();
customerRecord.append("customerId", custId );
const myHeader = new Headers({
'Accept':'application/json',
'Content-type':'application/json; charset=utf-8'
});
fetch(customerApi,{
method:'POST',
headers:myHeader,
body:customerRecord
})
.then(res => res.json())
.then(
(result) => {
this.setState({
singleCustomer:result,
isEditCustomer:true,
isAddCustomer:true
})
},(error) => {
this.setState({ error });
}
)
}
render() {
const { users } = this.state;
let customerForm;
if (this.state.isEditCustomer || this.state.isAddCustomer){
customerForm = <AddCustomer onAddFormSubmit = {this.onAddFormSubmit} singleCustomer = {this.state.singleCustomer}/>
}
return (
<div>
<Table celled textAlign='center'>
<Table.Header>
<Table.Row>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Address</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body >
{
users.map(user => (
<Table.Row key={user.customerId}>
<Table.Cell>{user.customerId}</Table.Cell>
<Table.Cell>{user.name}</Table.Cell>
<Table.Cell>{user.address}</Table.Cell>
<Table.Cell>
<Button color='blue' onClick = {()=>this.onEditCustomer(user.customerId)}>Edit</Button>
</Table.Cell>
<Table.Cell>
<Button color='red'>Delete</Button>
</Table.Cell>
</Table.Row>
))
}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='5'>
No of Pages
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
</div>
)
}
}
Here is ASP.NET Core controller for API
namespace CRUDReact.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
private readonly DataBaseContext _context;
public CustomersController(DataBaseContext context)
{
_context = context;
}
// GET: api/Customers
[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> GetCustomer()
{
return await _context.Customer.ToListAsync();
}
// GET: api/Customers/5
[HttpGet("{id}")]
public async Task<ActionResult<Customer>> GetCustomer(int id)
{
var customer = await _context.Customer.FindAsync(id);
if (customer == null)
{
return NotFound();
}
return customer;
}
// PUT: api/Customers/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPut("{id}")]
public async Task<IActionResult> PutCustomer(int id, Customer customer)
{
customer.CustomerId = id;
_context.Entry(customer).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CustomerExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Customers
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPost]
public async Task<ActionResult<Customer>> PostCustomer(Customer customer)
{
_context.Customer.Add(customer);
await _context.SaveChangesAsync();
return CreatedAtAction("GetCustomer", new { id = customer.CustomerId }, customer);
}
// DELETE: api/Customers/5
[HttpDelete("{id}")]
public async Task<ActionResult<Customer>> DeleteCustomer(int id)
{
var customer = await _context.Customer.FindAsync(id);
if (customer == null)
{
return NotFound();
}
_context.Customer.Remove(customer);
await _context.SaveChangesAsync();
return customer;
}
private bool CustomerExists(int id)
{
return _context.Customer.Any(e => e.CustomerId == id);
}
}
}
Perhaps you should update your endpoint to append customer ID?
const customerApi = 'https://localhost:44387/api/Customers/' + custId;

Setting up proper MongoDB implementation in React app

So, currently I'm working on internship React (MERN) app, which is a simple to-do list with ability to create, delete and edit todos. I will post some code from it, but you also can look at the full code on GitHub: https://github.com/Wonderio619/magisale-internship-todo
The next task is connecting my app to MongoDB. I have some "boilerplate" code - I alredy set up connection with MongoDB, also have Express router with routes like get all todos list, send todo to database, update todo with id, get todo with id:
const express = require("express");
const router = express.Router();
let Todo = require('../models/model')
// get all todo list with id
router.get('/', function (req, res) {
Todo.find()
.then((todos) => res.json(todos))
.catch((error) => res.send(error))
})
// send todo to database
router.post('/', function (req, res) {
let todo = new Todo();
todo.titleText = req.body.title;
todo.todoText = req.body.body;
todo.save(function (err) {
if (err)
res.send(err);
res.send('Todo successfully added!');
});
})
// get todo with id
router.get('/:todoId', function (req, res) {
Todo.findById(req.params.todoId)
.then(foundTodo => res.json(foundTodo))
.catch(error => res.send(error));
})
// updates todo with id
router.put('/:todoId', function (req, res) {
Todo.findOneAndUpdate({ _id: req.params.todoId }, req.body, { new: true })
.then((todo) => res.json(todo))
.catch((error) => res.send(error))
})
// deletes todo with id
router.delete('/:todoId', function (req, res) {
Todo.remove({ _id: req.params.todoId })
.then(() => res.json({ message: 'todo is deleted' }))
.catch((error) => res.send(error))
})
module.exports = router;
These routes used when corresponding methods from todo app are called:
import React, { Component } from 'react';
import './ToDo.css';
import Logo from './assets/logo.png';
import ToDoItem from './components/ToDoItem';
import AppBar from './components/AppBar';
import Popover from './components/Popover';
import { connect } from 'react-redux';
class ToDo extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
title: '',
todo: '',
};
};
componentDidMount = () => {
fetch("/api/todos")
.then(data => data.json())
.then(res => this.setState({ list: res.data }));
console.log(this.state.list)
};
createNewToDoItem = () => {
fetch("/api/todos", {
method: "post",
headers: new Headers({
"Content-Type": "application/json"
}),
body: JSON.stringify({
title: this.state.title,
body: this.state.todo
})
})
.catch(err => {
console.error(err);
});
if (this.state.title !== '' & this.state.todo !== '') {
this.props.createTodoItem(this.state.title, this.state.todo);
this.setState({ title: '', todo: '' });
}
};
handleTitleInput = e => {
this.setState({
title: e.target.value,
});
};
handleTodoInput = e => {
this.setState({
todo: e.target.value,
});
};
editItem = (i, updTitle, updToDo) => {
const modifyURL = "/api/todos/" + i;
fetch(modifyURL, {
method: "put",
headers: new Headers({
"Content-Type": "application/json"
}),
body: JSON.stringify({
title: updTitle,
todo: updToDo
})
})
.then(resp => {
if (!resp.ok) {
if (resp.status >= 400 && resp.status < 500) {
return resp.json().then(data => {
let error = { errorMessage: data.message };
throw error;
});
} else {
let error = {
errorMessage: "Please try again later. Server is not online"
};
throw error;
}
}
return resp.json();
})
.then(newTodo => {
let arr = this.props.list;
arr[i].title = updTitle;
arr[i].todo = updToDo;
this.setState({ updateList: true });
});
};
deleteItem = indexToDelete => {
const deleteURL = "/api/todos/" + indexToDelete;
fetch(deleteURL, {
method: "delete"
})
.then(resp => {
if (!resp.ok) {
if (resp.status >= 400 && resp.status < 500) {
return resp.json().then(data => {
let error = { errorMessage: data.message };
throw error;
});
} else {
let error = {
errorMessage: "Please try again later. Server is not online"
};
throw error;
}
}
return resp.json();
})
.then(() => {
this.props.deleteTodoItem(indexToDelete);
});
};
randId() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
}
eachToDo = (item, i) => {
return <ToDoItem
key={this.randId()}
title={item.title}
todo={item.todo}
deleteItem={this.deleteItem.bind(this, i)}
editItem={this.editItem.bind(this, i)}
/>
};
render() {
const { list } = this.props;
return (
<div className="ToDo">
<img className="Logo" src={Logo} alt="React logo" />
<AppBar />
<div className="ToDo-Container">
<div className="ToDo-Content">
{list.map(this.eachToDo)}
</div>
<div>
<Popover
toDoValue={this.state.todo}
titleValue={this.state.title}
titleOnChange={this.handleTitleInput}
toDoOnChange={this.handleTodoInput}
addHandler={this.createNewToDoItem}
/>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
list: state.list
}
}
const mapDispatchToProps = dispatch => {
return {
deleteTodoItem: id => {
dispatch({ type: "DELETE_TODO", id: id });
},
createTodoItem: (title, todo) => {
dispatch({ type: "CREATE_TODO", title: title, todo: todo });
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ToDo);
Note that "list" array from state is not really used, bacause I have initial list state in Redux state here( it may be implemented bad, but it is anyway):
const initState = {
list: [
{
title: 'Cup cleaning',
todo: "Wash and take away the Kurzhiy's cup from WC"
},
{
title: 'Smoking rollton',
todo: 'Do some rollton and cigarettes'
},
{
title: 'Curious dream',
todo: 'Build a time machine'
}
],
};
const rootReducer = (state = initState, action) => {
switch (action.type) {
case "DELETE_TODO":
let newList = state.list.filter((todo, index) => action.id !== index)
return {
...state,
list: newList
}
case "CREATE_TODO":
const title = action.title;
const todo = action.todo;
let createdList = [
...state.list,
{
title,
todo
}
]
return {
...state,
list: createdList
}
default:
return state;
}
}
export default rootReducer;
So, now I need some help - if I understand everything right, my list state should now be stored inside MongoDB database. But currently it is in Redux, how should I switch from current state implementation to MongoDB properly ?
Also I understand that my MongoDB implementation is far from perfection, I'm just newbie to this, but I need to solve following problems:
1) I tried to get all todos from database in ComponentDidMount method and save it in array, but console.log always show that array is empty smth definitely wrong there.
2) Also connection with database is not really set up, because in general I can only add todos to database, but delete or edit functions does not work, because I'm little stuck about how to implement this index stuff, should I use ObjectId property from MongoDB or should I pass indexes from my main component to database, and how ?
Also any global recommendations regarding proper mongodb implementaion and suggestions or fixes to my code will be greatly appreciated :)
It's not res.data but res that you should inject in your state. res.data is undefined so it won't update the state.list.
componentDidMount = () => {
fetch("/api/todos")
.then(data => data.json())
.then(jsonData => {
console.log('jsonData --', jsonData)
console.log('jsonData.data is empty!', jsonData.data)
this.setState({ list: jsonData })
});
};
1- To be able to update, you're sending an id. You may create id's in your db if that's the way you want to find your todos.
Please note that _id is different from id.
_id mongodb's ObjectId, it is not of type integer but of type ObjectId.
id is just a regular field that you created that is called id.
NB: Your req.params.todoId is an integer. While ObjectId is of type ObjectId! So you won't be able to query one with the wrong type.
var todoSchema = new Schema({
id: Number,
titleText: String,
todoText: String
});
2- Get your todo and update it thanks to the id. If it does not exist, it will be created thanks to the upsert option. Don't forget to cast in order to match your schema. title: req.body.title won't work because you defined it as titleText in your schema.
// updates todo with id
router.put('/:todoId', function (req, res) {
const data = {
titleText: req.body.title,
todoText: req.body.todo
}
Todo.findOneAndUpdate(
{ id: req.params.todoId }, // the query
{ $set: data }, // things to update
{ upsert: true } // upsert option
).then((todo) => res.json(todo))
.catch((error) => res.send(error))
})

Resources