iT邦幫忙

2022 iThome 鐵人賽

DAY 1
5
Software Development

.NET Core與React組合開發技系列 第 1 篇

.NET Core與React組合開發技_第01天_前言_專案建立與大致介紹

  • 分享至 

  • xImage
  •  

2022鐵人賽第一天文章,讀者朋友們好
來稍微探究一下於asp.net core中搭配React前端框架的開發
在這30天成蝶的過程

我想React本身很重ES6和Javascript一些基本語法
算還滿適合拿來當三框架中先拿來進行掌握的一門
(但也是最難掌握也很多人不太推先學的XD)

勉勵自己也將知識專業進行傳播
如文章對於你(可能是個小白)也可能是
只會React但不曉得如何結合.NET Core後端的
又或者只會.NET Core後端但不曉得怎麼和React進行結合的

我希望這系列文章
是個對上述這些開發者戰友們或者以往家教學員
有幫助讀起來不會吃力也很容易吸收的技術篇章

此系列會使用
NodeJs 16以上
和
visual studio 2022
(.Net6長期支援版本)

會在Windows作業系統上做筆記文章
當然若是Mac愛好者的朋友.Net Core (.Net6)也以克服跨作業系統的限制
並不侷限於Windows OS
但Mac環境有關visual studio相關操作可能就都要用cli和vscode來搭配了
因為Mac上的Visual Studio for Mac我較沒接觸

請各位先準備好上述這些IDE和開發環境
有任何誤植或者觀點不認同皆可進行一些開發經驗分享
和批評指教一同成長

開啟vs2022創建第一個React.js配asp.net core的新專案

https://ithelp.ithome.com.tw/upload/images/20220912/20107452aVYYfD6z5o.png

在此去命名專案名稱默認會配有一個.csproj(C#的專案檔)和.sln(方案)
方案中可包含一或多個專案

https://ithelp.ithome.com.tw/upload/images/20220912/201074520mmC2anYBj.png

選.NET6.0
https://ithelp.ithome.com.tw/upload/images/20220912/20107452Xu8A7gegHp.png

預設新專案建立好後就可看到如下專案結構
https://ithelp.ithome.com.tw/upload/images/20220912/20107452UPp0h5lpLb.png

有默認範本的asp.net core web api(相關先備知識可參閱過去技術部落格貼文)
於此系列可能就會稍微帶過

可以觀察到專案目錄下有一份前端的專案檔
裡面有熟悉的NodeJs package.json

https://ithelp.ithome.com.tw/upload/images/20220912/20107452ddHWa4IaZv.png

於後端C#專案中的範疇
主程式進入點會在Program.cs當中
~\MyReact1\Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();


app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html"); ;

app.Run();

到了.net6以後採用Minimal API
也跟過去.net3.1和.net5架構又有所不同了省略Startup.cs
和namespace外層包覆

一個後端Get請求抓取一個string List資料
~\MyReact1\Controllers\WeatherForecastController.cs

using Microsoft.AspNetCore.Mvc;

namespace MyReact1.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

於前端React Js中的範疇
我們前端程式進入點位於Index.js這支程式檔中
~\MyReact1\ClientApp\src\index.js

import 'bootstrap/dist/css/bootstrap.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
import reportWebVitals from './reportWebVitals';

const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');

ReactDOM.render(
  <BrowserRouter basename={baseUrl}>
    <App />
  </BrowserRouter>,
  rootElement);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://cra.link/PWA
serviceWorkerRegistration.unregister();

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

而當中間接進行App Component的Render
~\MyReact1\ClientApp\src\App.js
在App.js中又間接去存取專for web api存取的Component 也就是FetchData.js

import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';

import './custom.css'

export default class App extends Component {
  static displayName = App.name;

  render () {
    return (
      <Layout>
        <Route exact path='/' component={Home} />
        <Route path='/counter' component={Counter} />
        <Route path='/fetch-data' component={FetchData} />
      </Layout>
    );
  }
}

~\MyReact1\ClientApp\src\components\FetchData.js

import React, { Component } from 'react';

export class FetchData extends Component {
  static displayName = FetchData.name;

  constructor(props) {
    super(props);
    this.state = { forecasts: [], loading: true };
  }

  componentDidMount() {
    this.populateWeatherData();
  }

  static renderForecastsTable(forecasts) {
    return (
      <table className='table table-striped' aria-labelledby="tabelLabel">
        <thead>
          <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
          </tr>
        </thead>
        <tbody>
          {forecasts.map(forecast =>
            <tr key={forecast.date}>
              <td>{forecast.date}</td>
              <td>{forecast.temperatureC}</td>
              <td>{forecast.temperatureF}</td>
              <td>{forecast.summary}</td>
            </tr>
          )}
        </tbody>
      </table>
    );
  }

  render() {
    let contents = this.state.loading
      ? <p><em>Loading...</em></p>
      : FetchData.renderForecastsTable(this.state.forecasts);

    return (
      <div>
        <h1 id="tabelLabel" >Weather forecast</h1>
        <p>This component demonstrates fetching data from the server.</p>
        {contents}
      </div>
    );
  }

  async populateWeatherData() {
    const response = await fetch('weatherforecast');
    const data = await response.json();
    this.setState({ forecasts: data, loading: false });
  }
}

以上是一個大致前後端如何互動的程式碼導讀

我們可將專案運行起來
默認啟動起來(按綠色撥放按鈕)
預設由於還要做前置build因此等他一段時間會自動跳轉到真正的主頁 URL
這邊是兩個站台應用(因此會有各自不同的port)
後端7248,前端44481

https://ithelp.ithome.com.tw/upload/images/20220912/20107452QZU5yy8AUt.png

https://ithelp.ithome.com.tw/upload/images/20220912/20107452MvpU8LXcEf.png

https://ithelp.ithome.com.tw/upload/images/20220912/20107452RXPHz8BEZf.png

可看到React呼叫web api後呈現到頁面的結果
https://ithelp.ithome.com.tw/upload/images/20220912/201074522o5aTMbSaD.png

本篇已同步發表至個人部落格
https://coolmandiary.blogspot.com/2022/09/net-corereact01.html


下一篇
.NET Core與React組合開發技_第02天_調整React範本產生產品列表清單_JSX、元件狀態介紹
系列文
.NET Core與React組合開發技 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言