Monday 25 June 2018

PHP Tutorial

https://www.tutorialrepublic.com/php-tutorial/

MongoDB tutorial

https://www.youtube.com/playlist?list=PL6gx4Cwl9DGDQ5DrbIl20Zu9hx1IjeVhO

command

switch to/ create db

use xxx

drop database

db.dropDatabase()

insert

db.collectionName.insert(json)
db.collectionName.insert([jsons])

show collections

show collections

search

db.collectionName.find(json criteria)
db.collectionName.findOne()
db.collectionName.find(
    json criteria,
    {"name":1, _id:0}           display name, not _id
)
db.collectionName.find().limit(3)
db.collectionName.find().skip(2)

delete

db.collectionName.remove(json criteria)

update

db.collectionName.update(json criteria, json obj)

json criteria

{"position":"defenders", "age":21}

{
   $or:[
           {"position": "left wing"},
           {"position": "right wing"}
     ]
}

{"age": {$gt:30}}   gt>   lt<   gte>=    lte<=  ne!=

index

db.collectionName.find(json critera),explain("executionStats")
db.collectionName.ensureIndex({"age":1})
db.collectionName.getIndexes()
db.collectionName.droptIndex({"age":1})

aggregation and groups

db.collectionName.aggregate({
    $group:{
          _id: "$groupColumn",
          total: {$sum: 1},
          avg: {$avg: "avgColumn"},
          max: {$max: "maxColumn"
      }
})



json generator
https://next.json-generator.com/

mongoDB community
https://www.mongodb.com/download-center?jmp=nav#community

mongoDB compass
https://www.mongodb.com/download-center#compass

Studio 3T
https://studio3t.com/download-thank-you/?OS=win64

Sunday 24 June 2018

react + redux schedule





Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from "react-redux";
import store from "./store";
import 'bootstrap/dist/css/bootstrap.min.css';

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, document.getElementById('root'));

registerServiceWorker();

---------------------------------------------------------------------------------
App.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import './App.css';
import AddForm from './forms/add';
import DeleteForm from './forms/delete';
import UpdateForm from './forms/update'
import { display_rawSchedules } from './quickFunctions.js';

class App extends Component {
    render() {
        return (
            <div>
                {display_rawSchedules(this.props.schedules)}
                <AddForm />
                <DeleteForm schedules={this.props.schedules} />
                <UpdateForm schedules={this.props.schedules} />
            </div>
        );
    }
}

export default connect(
    (store) => {
        return {
            schedules: store.schedules.schedules,
        };
    }
)(App);

---------------------------------------------------------
store.js

import { applyMiddleware, createStore } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import promiseMiddleware from 'redux-promise-middleware';

import reducer from "./reducers";

const middleware = applyMiddleware(promiseMiddleware(), thunk, logger);

export default createStore(reducer, middleware);

------------------------------------------------------------------------------
quickFunctions.js

import React from 'react';

export const display_rawSchedules = (data) => {

    const scheduleView = data.map((item, index) => {

        const matchView = data[index].matches.map((item2, index2) =>
            <div key={index2}>
                {"{"}
                home: {item2.home}, away: {item2.away},
                home score: {item2.homeScore}, away score: {item2.awayScore}
                {"}, "}
            </div>
        );

        return (<div key={index}>
            date: {item.date.toDateString()}<br />
            matches: {matchView}<br />
        </div>);

    })
    return (<div>{scheduleView}</div>);

}

export const dateToString = (date) => {
    const year = date.getFullYear().toString();
    const month = date.getMonth() + 1;
    const month0 = month < 10 ? '0' + month.toString() : month.toString();
    const day = date.getDate();
    const day0 = day < 10 ? '0' + day.toString() : day.toString();
    const newDate = year + '-' + month0 + '-' + day0;
    return newDate;
};

export const stringToDate = (input_string) => {
    const year_month_day = input_string.split('-');
    const year = parseInt(year_month_day[0]);
    const month = parseInt(year_month_day[1]) - 1;
    const day = parseInt(year_month_day[2]);
    return new Date(year, month, day);
}

----------------------------------------------------------------------
actions/scheduleAction.js

export function addSchedule(form) {
    return {
        type: "add_schedule",
        payload: form
    }
}

export function deleteAll(schedule_index) {
    return {
        type: "delete_all",
        payload: schedule_index
    }
}

export function deleteSingle(schedule_index, match_index) {
    return {
        type: "delete_single",
        payload: {
            scheduleIndex: schedule_index,
            matchIndex: match_index,
        }
    }
}

export function updateSchedule(form, schedule_index, match_index) {
    return {
        type: "update_schedule",
        payload: {
            form: form,
            scheduleIndex: schedule_index,
            matchIndex: match_index,
        }
    }
}

--------------------------------------------------------------------
reducers/index.js

import { combineReducers } from 'redux';
import schedules from "./scheduleReducer";

export default combineReducers(
    {
        schedules
    })

-------------------------------------------------------
reducers/scheduleReducer.js

import { stringToDate, dateToString } from '../quickFunctions'

export default function reducer(
    state = {
        schedules: [
            {
                date: new Date(2018, 4, 22),
                matches: [
                    { home: "santos", away: "real garcilaso", homeScore: 0, awayScore: 0 },
                    { home: "atletico nacional", away: "colo colo", homeScore: 0, awayScore: 0 },
                    { home: "corinthians", away: "millonarios", homeScore: 0, awayScore: 1 },
                    { home: "independiente", away: "deportivolara", homeScore: 2, awayScore: 0 },
                ]
            },
            {
                date: new Date(2018, 4, 21),
                matches: [
                    { home: "toronto fc", away: "fc dallas", homeScore: 0, awayScore: 2 },
                    { home: "houston dynamo", away: "new york city fc", homeScore: 2, awayScore: 1 },
                    { home: "portland thorns fc", away: "utah royals fc", homeScore: 2, awayScore: 1 },
                    { home: "los angeles galaxy", away: "san joes earthquakes", homeScore: 0, awayScore: 0 },
                ]
            },
            {
                date: new Date(2018, 5, 4),
                matches: [
                    { home: "thailand", away: "china pr", homeScore: 0, awayScore: 1 },
                    { home: "austria", away: "germany", homeScore: 3, awayScore: 1 },
                    { home: "england", away: "nigeria", homeScore: 1, awayScore: 0 },
                    { home: "sweden", away: "denmark", homeScore: 0, awayScore: 0 },
                ]
            },
            {
                date: new Date(2018, 4, 28),
                matches: [
                    { home: "brazil", away: "croatia", homeScore: 2, awayScore: 0 },
                    { home: "costa rica", away: "northern ireland", homeScore: 3, awayScore: 0 },
                    { home: "saudi arabia", away: "peru", homeScore: 0, awayScore: 3 },
                    { home: "bahia", away: "gremio", homeScore: 0, awayScore: 1 },
                ]
            },
        ],

        activeTab: "Monday",
        dateFilter: "",
    },
    action
) {
    switch (action.type) {
        case "add_schedule": {

            const newMatch = {
                home: action.payload.home,
                away: action.payload.away,
                homeScore: action.payload.homeScore,
                awayScore: action.payload.awayScore,
            };

            const newSchedules = [...state.schedules];
            const findDate_index = newSchedules.findIndex(x => dateToString(x.date) === action.payload.date);

            //add to existing schedule
            if (findDate_index >= 0) {
                newSchedules[findDate_index].matches.push(newMatch);
            }
            //create new schedule
            else {
                const newSchedule =
                    {
                        date: stringToDate(action.payload.date),
                        matches: [
                            newMatch,
                        ]
                    };

                newSchedules.push(newSchedule);
            }

            return { ...state, schedules: newSchedules }
        }

        case "delete_all": {
            const newSchedules = [...state.schedules];
            newSchedules.splice(action.payload, 1);

            return { ...state, schedules: newSchedules }
        }

        case "delete_single": {
            const newSchedules = [...state.schedules];
            newSchedules[action.payload.scheduleIndex].
                matches.splice(action.payload.matchIndex, 1);

            return { ...state, schedules: newSchedules }
        }

        case "update_schedule": {
            const newSchedules = [...state.schedules];

            newSchedules[action.payload.scheduleIndex].
                matches[action.payload.matchIndex] = {
                home: action.payload.form.home,
                away: action.payload.form.away,
                homeScore: action.payload.form.homeScore,
                awayScore: action.payload.form.awayScore,
                }

            return { ...state, schedules: newSchedules }
        }

        default:
            break;
    }
    return state;
}

-------------------------------------------------------------------------------
forms/add.js

import React, { Component } from 'react';
import { Button, Form, FormGroup, Input } from 'reactstrap';
import { stringToDate } from '../quickFunctions.js';
import { connect } from 'react-redux';
import { addSchedule } from '../actions/scheduleAction';
import '../App.css';

export class AddForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            date: "",
            home: "",
            away: "",
            homeScore: 0,
            awayScore: 0,
            status: "",
        };
    }

    handle_submit(e) {

        if (this.state.home === "" || this.state.away === "" || this.state.date === "") {
            return false;
        }
        else {
            const formData = {
                date: this.state.date,
                home: this.state.home,
                away: this.state.away,
                homeScore: this.state.homeScore,
                awayScore: this.state.awayScore,
            };

            this.props.dispatch(addSchedule(formData));
        }

        e.preventDefault();

        const messageStatus = "successfully added to " + stringToDate(this.state.date).toDateString();
        this.setState({ status: messageStatus });
    }
    render() {
        return (
            <div className="my-schedule-form-add">
                <h4>Add Schedule <span className="my-status">{this.state.status}</span></h4>
                <Form inline onSubmit={(e) => this.handle_submit(e)}>
                    <FormGroup >
                        <Input type="date" bsSize="sm" name="matchDate" placeholder="Match Date" required="required"
                            onChange={(e) => this.setState({ date: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <Input bsSize="sm" placeholder="Home Team" required="required"
                            onChange={(e) => this.setState({ home: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <Input bsSize="sm" placeholder="Away Team" required="required"
                            onChange={(e) => this.setState({ away: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <Input type="number" bsSize="sm" placeholder="Home Score"
                            onChange={(e) => this.setState({ homeScore: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <Input type="number" bsSize="sm" placeholder="Away Score"
                            onChange={(e) => this.setState({ awayScore: e.target.value })} />
                    </FormGroup>

                    <Button size="sm" type="submit" onClick={() => this.setState({ status: "" })}> Submit</Button>
                </Form>
            </div>
        );
    }
}

export default connect(
    (store) => {
        return {
            schedules: store.schedules.schedules,
        };
    }
)(AddForm);

------------------------------------------------------------------
forms/delete.js

import React, { Component } from 'react';
import { Button, Input, Row, Col } from 'reactstrap';
import { dateToString } from '../quickFunctions.js';
import { connect } from 'react-redux';
import { deleteAll, deleteSingle } from '../actions/scheduleAction.js';
import '../App.css';

export class DeleteForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedMatch: 0,
            selectedDate: "",
            dateDisable: false,
            matchDisable: false,
            status:"",
        };
    }

    handle_selectDate(e) {
        this.setState({
            dateDisable: true,
            selectedDate: e.target.value,
        });

    }

    handle_selectMatch(e) {
        this.setState({
            matchDisable: true,
            selectedMatch: parseInt(e.target.value.split(' ')[0].slice(1)) - 1,
        });
    }

    handle_deleteSingle() {
        const selectedSchedule_index = this.props.schedules.findIndex(
            x => dateToString(x.date) === this.state.selectedDate);

        this.props.dispatch(
            deleteSingle(selectedSchedule_index, this.state.selectedMatch));

        const messageStatus = "deleted " + this.state.selectedDate + " match " +
            (this.state.selectedMatch + 1).toString();
        this.setState({ status: messageStatus });
    }

    handle_deleteAll() {
        const selectedSchedule_index = this.props.schedules.findIndex(
            x => dateToString(x.date) === this.state.selectedDate);

        this.props.dispatch(deleteAll(selectedSchedule_index));

        const messageStatus = "deleted " + this.state.selectedDate;
        this.setState({ status: messageStatus });
    }

    render() {
        const dateOptions = this.props.schedules.
            map((item, index) => {
                const dateString = dateToString(item.date);
                return (
                    <option key={dateString}>{dateString}</option>);
            }).
            sort((a, b) => {
                return a.key.localeCompare(b.key)
            });

        dateOptions.unshift(<option key={-1} disabled={this.state.dateDisable}>
            select date</option>);

        const selectedSchedule_index = this.props.schedules.findIndex(
            x => dateToString(x.date) === this.state.selectedDate);

        const matchOptions = selectedSchedule_index >= 0 ?

            this.props.schedules[selectedSchedule_index].matches.
                map((item, index) =>
                    <option key={index}>#{index + 1} {item.home} vs {item.away}</option>
                )
            : [];

        matchOptions.unshift(<option key={-1} disabled={this.state.matchDisable}>
            select match</option>);

        return (
            <div className="my-schedule-form-delete">
                <h4>Delete Schedule <span className="my-status">{this.state.status}</span></h4>
                <Row>
                    <Col xs="3">
                        <Input type="select" bsSize="sm"
                            onChange={(e) => this.handle_selectDate(e)}>
                            {dateOptions}</Input>
                    </Col>
                    <Col xs="5">
                        <Input type="select" bsSize="sm" disabled={!this.state.dateDisable}
                            onChange={(e) => this.handle_selectMatch(e)}>
                            {matchOptions}</Input>
                    </Col>
                    <Col xs="2">
                        <Button size="sm" disabled={!this.state.matchDisable}
                            onClick={() => this.handle_deleteSingle()}>
                            Delete single</Button>
                    </Col>
                    <Col xs="2">
                        <Button size="sm" disabled={!this.state.dateDisable}
                            onClick={() => this.handle_deleteAll()}>
                            Delete all</Button>
                    </Col>
                </Row>
            </div>
        );
    }
}


export default connect(
    (store) => {
        return {
            schedules: store.schedules.schedules,
        };
    }
)(DeleteForm);

------------------------------------------------------------------
forms/update.js

import React, { Component } from 'react';
import { Button, Form, FormGroup, Input, Row, Col } from 'reactstrap';
import { dateToString, stringToDate } from '../quickFunctions.js';
import { connect } from 'react-redux';
import { updateSchedule} from '../actions/scheduleAction.js';
import '../App.css';

export class UpdateForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedMatch: 0,
            selectedDate: "",
            dateDisable: false,
            matchDisable: false,
            home: "Home Team",
            away: "Away Team",
            homeScore: 0,
            awayScore: 0,
            status:"select date -> match -> update input -> submit",
        };
    }

    handle_selectDate(e) {
        this.setState({
            dateDisable: true,
            selectedDate: e.target.value,
        });

    }

    handle_selectMatch(e) {
        const matchIndex = parseInt(e.target.value.split(' ')[0].slice(1)) - 1;
        const scheduleIndex = this.props.schedules.findIndex(
            x => dateToString(x.date) === this.state.selectedDate);

        const matchSelected = this.props.schedules[scheduleIndex].matches[matchIndex];

        this.setState({
            matchDisable: true,
            selectedMatch: matchIndex,
            home: matchSelected.home,
            away: matchSelected.away,
            homeScore: matchSelected.homeScore,
            awayScore: matchSelected.awayScore,
        });
    }

    handle_submit(e) {

        if (this.state.home === "" || this.state.away === "") {
            return false;
        }
        else {
            const formData = {
                home: this.state.home,
                away: this.state.away,
                homeScore: this.state.homeScore,
                awayScore: this.state.awayScore,
            };

            const selectedSchedule_index = this.props.schedules.findIndex(
                x => dateToString(x.date) === this.state.selectedDate);

            this.props.dispatch(updateSchedule(
                formData,
                selectedSchedule_index,
                this.state.selectedMatch,
            ));
        }

        e.preventDefault();

        const messageStatus = "updated " + this.state.selectedDate + " match " +
            (this.state.selectedMatch+1).toString();
        this.setState({ status: messageStatus });
    }

    render() {
        const dateOptions = this.props.schedules.
            map((item, index) => {
                const dateString = dateToString(item.date);
                return (
                    <option key={dateString}>{dateString}</option>);
            }).
            sort((a, b) => {
                return a.key.localeCompare(b.key)
            });

        dateOptions.unshift(<option key={-1} disabled={this.state.dateDisable}>
            select date</option>);

        const selectedSchedule_index = this.props.schedules.findIndex(
            x => dateToString(x.date) === this.state.selectedDate);

        const matchOptions = selectedSchedule_index >= 0 ?

            this.props.schedules[selectedSchedule_index].matches.
                map((item, index) =>
                    <option key={index}>#{index + 1} {item.home} vs {item.away}</option>
                )
            : [];

        matchOptions.unshift(<option key={-1} disabled={this.state.matchDisable}>
            select match</option>);

        return (
            <div className="my-schedule-form-update">
                <h4>update Schedule <span className="my-status">{this.state.status}</span></h4>
                <Row>
                    <Col xs="3">
                        <Input type="select" bsSize="sm"
                            onChange={(e) => this.handle_selectDate(e)}>
                            {dateOptions}</Input>
                    </Col>
                    <Col xs="5">
                        <Input type="select" bsSize="sm" disabled={!this.state.dateDisable}
                            onChange={(e) => this.handle_selectMatch(e)}>
                            {matchOptions}</Input>
                    </Col>                                     
                </Row>

                <Form inline onSubmit={(e) => this.handle_submit(e)} >             
                    <FormGroup >
                        <Input bsSize="sm" placeholder={this.state.home}
                            onChange={(e) => this.setState({ home: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <Input bsSize="sm" placeholder={this.state.away}
                            onChange={(e) => this.setState({ away: e.target.value })} />
                    </FormGroup>
                    <FormGroup >
                        <span id="update_homeScore">
                            <span className="my-tooltip">home score</span>
                            <Input type="number" bsSize="sm" placeholder={this.state.homeScore}
                                onChange={(e) => e.target.value !== "" ? this.setState({ homeScore: e.target.value }) : null}
                                disabled={this.state.disable_input} />
                        </span>
                    </FormGroup>
                    <FormGroup >
                        <span id="update_awayScore">
                            <span className="my-tooltip">away score</span>
                            <Input type="number" bsSize="sm" placeholder={this.state.awayScore}
                                onChange={(e) => e.target.value !== "" ? this.setState({ awayScore: e.target.value }) : null}
                                disabled={this.state.disable_input} />
                        </span>
                    </FormGroup>

                    <Button size="sm" type="submit" disabled={!this.state.matchDisable}
                        onClick={() => this.setState({ status: "select date -> match -> update input -> submit" })}>
                        Submit</Button>
                </Form>
            </div>
        );
    }
}


export default connect(
    (store) => {
        return {
            schedules: store.schedules.schedules,
        };
    }
)(UpdateForm);

----------------------------------------------------------

reference:
http://chuanshuoge2.blogspot.com/search?q=react-redux
http://chuanshuoge2.blogspot.com/search?q=react+schedule
http://chuanshuoge2.blogspot.com/search?q=react+git
http://chuanshuoge2.blogspot.com/2018/06/react-redux-schedule.html


Mega Construction Projects Build


Sunday 17 June 2018

reactstrap Carousel card

project site: http://chuanshuoge1.github.io/reactstrap
js

import React, { Component } from 'react';
import {
    Carousel,
    CarouselItem,
    CarouselControl,
    CarouselIndicators,
    CarouselCaption,
    Row, Col
} from 'reactstrap';

import {
    Card, CardImg, CardText, CardBody, CardLink,
    CardTitle, CardSubtitle
} from 'reactstrap';

export const Home = () => (
    <div>
        <h1>Welcome to the Bob's Website!</h1>
        <MyCarousel />
        {MyCard()}
    </div>
)

const items = [
    {
        id: 1,
        altText: '',
        caption: '',
        src: 'https://github.com/chuanshuoge1/reactstrap/blob/gh-pages/image/1.png?raw=true'
    },
    {
        id: 2,
        altText: '',
        caption: '',
        src: 'https://github.com/chuanshuoge1/reactstrap/blob/gh-pages/image/2.png?raw=true'
    },
    {
        id: 3,
        altText: '',
        caption: '',
        src: 'https://github.com/chuanshuoge1/reactstrap/blob/gh-pages/image/3.png?raw=true'
    }
];

class MyCarousel extends Component {
    constructor(props) {
        super(props);
        this.state = { activeIndex: 0 };
        this.next = this.next.bind(this);
        this.previous = this.previous.bind(this);
        this.goToIndex = this.goToIndex.bind(this);
        this.onExiting = this.onExiting.bind(this);
        this.onExited = this.onExited.bind(this);
    }

    onExiting() {
        this.animating = true;
    }

    onExited() {
        this.animating = false;
    }

    next() {
        if (this.animating) return;
        const nextIndex = this.state.activeIndex === items.length - 1 ? 0 : this.state.activeIndex + 1;
        this.setState({ activeIndex: nextIndex });
    }

    previous() {
        if (this.animating) return;
        const nextIndex = this.state.activeIndex === 0 ? items.length - 1 : this.state.activeIndex - 1;
        this.setState({ activeIndex: nextIndex });
    }

    goToIndex(newIndex) {
        if (this.animating) return;
        this.setState({ activeIndex: newIndex });
    }

    render() {
        const { activeIndex } = this.state;
        const marginLeft = (window.innerWidth / 2 - 150).toString() + 'px';

        const slides = items.map((item) => {
            return (
                <CarouselItem
                    className="my-Carousel"
                    tag="div"
                    key={item.id}
                    onExiting={this.onExiting}
                    onExited={this.onExited}
                >
                    <a href="https://www.tsn.ca/soccer" target="_blank">
                        <img className="my-CarouselImage" style={{ marginLeft: marginLeft }}
                            src={item.src} alt={item.altText} />
                    </a>

                </CarouselItem>
            );
        });

        return (
            <div>
                <Carousel
                    activeIndex={activeIndex}
                    next={this.next}
                    previous={this.previous}
                >
                    <CarouselIndicators items={items} activeIndex={activeIndex} onClickHandler={this.goToIndex} />
                    {slides}
                    <CarouselControl direction="prev" directionText="Previous" onClickHandler={this.previous} />
                    <CarouselControl direction="next" directionText="Next" onClickHandler={this.next} />
                </Carousel>
            </div>
        );
    }
}

const MyCard = () => {

    return (
        <div>
            <Row>
                <Col sm={{ size: 6, offset: 3 }}>
                    <Card style={{ backgroundColor: 'lightgrey', borderColor: '#555' }}>
                        <CardBody>
                            <CardTitle>Bob's Blog</CardTitle>
                        </CardBody>
                        <img src="https://github.com/chuanshuoge1/reactstrap/blob/gh-pages/image/4.png?raw=true" alt="blog" />
                        <CardBody>
                            <CardText>Blog links:</CardText>
                            <CardLink href="http://chuanshuoge2.blogspot.com/">blog1</CardLink>
                            <CardLink href="http://chuanshuoge1.blogspot.com/">blog2</CardLink>
                        </CardBody>
                    </Card>
                </Col>
            </Row>
        </div>
    );
};

-------------------------------------------------
css

.my-Carousel {
    max-width: 100%;
    height:300px;
    background: black;
}

.my-CarouselImage {
    height:300px;
}


reference:
https://reactstrap.github.io/components/carousel/
https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
https://stackoverflow.com/questions/39066671/react-update-component-margin-top-with-jquery

Saturday 16 June 2018

react axios + aspcore webapi

axios get data from webapi


axios post to webapi, items are added

axios delete request to webapi, item with id '2' is deleted

axios update request to webapi, item id '3' sam->Sam true->false

axios try to delete and update item id '4', item not found on webapi, error response

stop webapi, axios receives network error response

webapi header

webapi

 webapi startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore;
using webApi.Models;

namespace webApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAllOrigins", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

            });
            services.AddDbContext<Context>(opt =>
                opt.UseInMemoryDatabase("MyApiDb"));
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseCors("AllowAllOrigins");
            app.UseMvc();
        }
    }
}

-----------------------------------------------------------------------------
webapi ItemsController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using webApi.Models;

namespace webApi.Controllers
{
    [Produces("application/json")]
    [Route("api/values")]
    [EnableCors("AllowAllOrigins")]
    public class ItemsController : Controller
    {
        private readonly Context _context;

        public ItemsController(Context context)
        {
            _context = context;


            if (_context.Items.Count() == 0)
            {
                _context.Items.Add(new Item
                {
                    Name = "bob",
                    IsComplete = true,
                });

                _context.SaveChanges();
            }
        }

        // GET: api/values
        [HttpGet]
        public IEnumerable<Item> GetItems()
        {
            return _context.Items.ToList();
        }

        // GET: api/values/5
        [HttpGet("{id}")]
        public async Task<IActionResult> GetItem([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var item = await _context.Items.SingleOrDefaultAsync(m => m.Id == id);

            if (item == null)
            {
                return NotFound();
            }

            return Ok(item);
        }

        // PUT: api/values/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutItem([FromRoute] int id, [FromBody] Item item)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != item.Id)
            {
                return BadRequest();
            }

            _context.Entry(item).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ItemExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return Ok();
        }

        // POST: api/values
        [HttpPost]
        public async Task<IActionResult> PostItem([FromBody] Item item)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _context.Items.Add(item);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetItem", new { id = item.Id }, item);
        }

        // DELETE: api/values/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteItem([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var item = await _context.Items.SingleOrDefaultAsync(m => m.Id == id);
            if (item == null)
            {
                return NotFound();
            }

            _context.Items.Remove(item);
            await _context.SaveChangesAsync();

            return Ok(item);
        }

        private bool ItemExists(int id)
        {
            return _context.Items.Any(e => e.Id == id);
        }
    }
}

-------------------------------------------------------------------------
webapi context.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace webApi.Models
{
    public class Context:DbContext
    {
        public Context(DbContextOptions<Context> options)
            : base(options)
        {
        }

        public DbSet<Item> Items { get; set; }
    }
}

----------------------------------------------------------
webapi Item.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace webApi.Models
{
    public class Item
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

---------------------------------------------------------
react app.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
import { Button, Form, FormGroup, Input } from 'reactstrap';

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            items: [],
            name_input: "",
            name_update: "",
            iscomplete_input: "",
            iscomplete_update:"",
            delete_id: -1,
            update_id: -1,
            get_status: "",
            add_status: "",
            delete_status: "",
            update_status: "",
        }
    }

    handle_getAll() {

        axios.get(myUrl)
            .then(res => {
                const Data = res.data;
                this.setState({ items: Data });
                res.statusText ? this.setState({ get_status: res.statusText }) : null;
            })
            .catch(error => {
                this.setState({ get_status: error.message })
            });
    }

    handle_post(e) {
        e.preventDefault();

        const name = this.state.name_input;
        const complete = this.state.iscomplete_input === "true" ? true : false;

        if (name !== "") {
            axios.post(myUrl, { name: name, isComplete: complete })
                .then(res => {
                    console.log(res);
                    console.log(res.data);
                    res.statusText ? this.setState({ add_status: res.statusText }) : null;

                    return this.handle_getAll();
                })
                .catch(error => {
                    this.setState({ add_status: error.message })
                });
        }

    }

    handle_delete(e) {
        e.preventDefault();

        const id = this.state.delete_id;
        const delete_url = myUrl + '/' + id.toString();

        axios.delete(delete_url)
            .then(res => {
                console.log(res);
                console.log(res.data);
                res.statusText ? this.setState({ delete_status: res.statusText }) : null;

                return this.handle_getAll();
            })
            .catch(error => {
                this.setState({ delete_status: error.message });
            });

    }

    handle_update(e) {
        e.preventDefault();

        const id = this.state.update_id;
        const update_url = myUrl + '/' + id.toString();
        const name = this.state.name_update;
        const complete = this.state.iscomplete_update === "true" ? true : false;

        if (name !== "") {
            axios.put(update_url, { id: id, name: name, isComplete: complete })
                .then(res => {
                    console.log(res);
                    console.log(res.data);
                    res.statusText ? this.setState({ update_status: res.statusText }) : null;

                    return this.handle_getAll();
                })
                .catch(error => {
                    this.setState({ update_status: error.message })
                });
        }
    }

    render() {
        const show_state = {
            name_input: this.state.name_input,
            name_update: this.state.name_update,
            isComplete_input: this.state.iscomplete_input,
            isComplete_update: this.state.iscomplete_update,
            delete_id: this.state.delete_id,
            update_id: this.state.update_id,
            get_status: this.state.get_status,
            add_status: this.state.add_status,
            delete_status: this.state.delete_status,
            update_status: this.state.update_status,
        }

        const show_state_by_line = JSON.stringify(show_state).split(",").
            map((item, index) => (
                <div key={index}>{item}</div>
            ));

        const complete_options = [
            <option key={1}>false</option>,
            <option key={2}>true</option>
            ]

        return (
            <div >
                this.state:
                {show_state_by_line}
                <br />

                <Button size="sm" onClick={() => this.handle_getAll()}> get all</Button>
                {this.state.get_status}
                {arrayToString_func(this.state.items)}

                <Form inline onSubmit={(e) => this.handle_post(e)}>
                    <FormGroup >
                        add item:
                        <Input type="text" bsSize="sm" placeholder="name" required="required"
                            onChange={(e) => this.setState({ name_input: e.target.value, add_status: "" })} />
                        <Input type="select" bsSize="sm"
                            onChange={(e) => this.setState({ iscomplete_input: e.target.value, add_status: "" })}>
                            {complete_options}</Input>
                        {this.state.add_status}
                    </FormGroup>

                    <Button size="sm" type="submit"> post</Button>
                </Form>
                <br />

                <Form inline onSubmit={(e) => this.handle_delete(e)}>
                    <FormGroup >
                        Delete id:
                        <Input type="number" bsSize="sm" placeholder={-1} required="required"
                            onChange={(e) => this.setState({ delete_id: parseInt(e.target.value), delete_status: "" })} />
                        {this.state.delete_status}
                    </FormGroup>

                    <Button size="sm" type="submit"> delete</Button>
                </Form>
                <br />

                <Form inline onSubmit={(e) => this.handle_update(e)}>
                    <FormGroup >
                        Update id:
                        <Input type="number" bsSize="sm" placeholder={-1} required="required"
                            onChange={(e) => this.setState({ update_id: parseInt(e.target.value), update_status: "" })} />
                        <Input type="text" bsSize="sm" placeholder="name" required="required"
                            onChange={(e) => this.setState({ name_update: e.target.value, update_status: "" })} />
                        <Input type="select" bsSize="sm"
                            onChange={(e) => this.setState({ iscomplete_update: e.target.value, update_status: "" })}>
                            {complete_options}</Input>
                        {this.state.update_status}
                    </FormGroup>

                    <Button size="sm" type="submit"> update</Button>
                </Form>
            </div>
        );
    }
}

const arrayToString_func = (array_input) => (
    <ul>{
        array_input.map((item, index) => (
            <li key={index}>{JSON.stringify(item)}</li>
        ))
    }
    </ul>
);

const myUrl = "http://localhost:53664/api/values";

export default App;

-----------------------------------------------------------
reference:

http://chuanshuoge2.blogspot.com/2018/06/react-aspnet.html