はじめに
React+Asp.net Core Web APIを使用していた際にAPIからデータを取得するのに手間取ったため備忘をかねて記事にします。
遭遇した問題
C#のプロジェクト作成では初めからテンプレートとして「React+ASP.Net Core WebAPI」のプロジェクトが存在します。そのテンプレートと同じようにAPIを作成しReactから参照した際に画面上に表示されずコンソールを確認すると、JSON変換時に以下のようなエラーメッセージが出力されました。
SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON {stack: 'SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON', message: 'Unexpected token '<', "<!doctype "... is not valid JSON'}
作成したWebAPIに問題があるのかと思いSwagger上で確認するとレスポンスは問題なさそうでした。
ただしReactからアクセスしているURLを直接ブラウザで開いたところJSONのレスポンスではなく普通に作成中のHTMLのページが開いてしまいました。
出力されているエラーのUnexpected token '<'
というのはHTMLタグのことのようです。
原因
使用するAPIをViteのコンフィグにも設定していなかった。そのためアクセスしていたURLがJSONではなくHTMLページを返却したことが原因でした。
これだとわけがわからないと思うので詳細に説明します。まず初めにReact+Asp.net Coreプロジェクトのテンプレートで作成できるWeatherForecastのアプリでWebAPIのURLと実際にアクセスしているURLを確認しました。
- WebAPIのURL:
https://localhost:7280/WeatherForecast
- アクセスしているURL:
https://localhost:5173/weatherforecast
その結果、アクセスしているポートが異なるということがわかりました。7280
はAsp.net Coreアプリ、5173
はReactアプリのポートです。てっきり直接APIをたたいていると思っていたのですがそうではないようでびっくりしました。
上記のポートを中継するような処理が必要であることは明白であるためWeatherForecast
でプロジェクトを検索したところvite.config.js
内で以下のようなコードを発見しました。
// https://vitejs.dev/config/
export default defineConfig({
plugins: [plugin()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
'^/weatherforecast': {
target,
secure: false
}
},
port: 5173,
https: {
key: fs.readFileSync(keyFilePath),
cert: fs.readFileSync(certFilePath),
}
}
})
上記のコードでVite側で調整をしていたようです。
解決法
vite.config.js
のproxy
に作成したAPIを追加することで解決しました。
// https://vitejs.dev/config/
export default defineConfig({
plugins: [plugin()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
'^/weatherforecast': {
target,
secure: false
- }
+ },
+ '^/api/todolist/': {
+ target,
+ secure: false
+ },
+ '^/hello': {
+ target,
+ secure: false
+ }
},
port: 5173,
https: {
key: fs.readFileSync(keyFilePath),
cert: fs.readFileSync(certFilePath),
}
}
})
おわりに
Microsoft様のサンプルコードはたまにこういうことがあるので油断できないです。