在vs2022中建立ASP.NET CORE MVC项目,项目结构如下
MyVueApp/ ├── ClientApp/ # Vue 3 前端代码 │ ├── src/ │ │ ├── components/ │ │ ├── views/ │ │ ├── router/ │ │ ├── store/ │ │ └── App.vue │ ├── package.json │ └── vite.config.js ├── Controllers/ ├── Views/ ├── wwwroot/ └── Program.cs
步骤 1:创建项目并配置后端
1.1 创建 ASP.NET Core MVC 项目
dotnet new mvc -n MyVueApp -f net5.0
cd MyVueApp
1.2 安装必要的 NuGet 包
<!-- 编辑 MyVueApp.csproj 文件 -->
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- 添加Spa服务支持 -->
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.*" />
</ItemGroup>
</Project>
1.3 配置 Program.cs
// Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
// 添加 MVC 服务
builder.Services.AddControllersWithViews();
var app = builder.Build();
// 配置中间件管道
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// 为静态文件提供服务
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
// MVC 路由
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// 用于开发环境的 Vue 开发服务器代理
if (app.Environment.IsDevelopment())
{
// 配置 Vue 开发服务器的代理
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
// Vue 开发服务器运行在 3000 端口
if (app.Environment.IsDevelopment())
{
spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
}
});
}
else
{
// 生产环境:提供编译后的 Vue 文件
app.Map(new PathString("/clientapp"), clientApp =>
{
clientApp.UseSpaStaticFiles();
clientApp.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp/dist";
});
});
}
app.Run();
步骤 2:创建 Vue 3 前端应用
2.1 创建 Vue 3 项目
在项目根目录下:
# 使用 Vite 创建 Vue 3 项目(推荐)
npm create vue@latest ClientApp -- --template vue
# 或者使用 Vue CLI
# vue create ClientApp
cd ClientApp
npm install
2.2 安装 Vue Router 和 Vuex(可选)
npm install vue-router@4 vuex@next axios
2.3 配置 Vite
// ClientApp/vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'url'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:5000', // ASP.NET Core 后端地址
changeOrigin: true
}
}
},
build: {
outDir: 'dist',
assetsDir: 'assets'
}
})
步骤 3:创建 Vue 应用结构
3.1 主入口文件
// ClientApp/src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 创建 Vue 应用实例
const app = createApp(App)
// 使用路由和状态管理
app.use(router)
app.use(store)
// 挂载到 #app 元素
app.mount('#app')
3.2 Vue 路由配置
// ClientApp/src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue'
import ProductsView from '../views/ProductsView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: AboutView
},
{
path: '/products',
name: 'products',
component: ProductsView
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
3.3 Vuex 状态管理(可选)
// ClientApp/src/store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
counter: 0,
user: null,
products: []
},
mutations: {
increment(state) {
state.counter++
},
setUser(state, user) {
state.user = user
},
setProducts(state, products) {
state.products = products
}
},
actions: {
async fetchProducts({ commit }) {
// 调用 API 获取产品数据
const response = await fetch('/api/products')
const products = await response.json()
commit('setProducts', products)
}
},
getters: {
getProductCount: state => state.products.length
}
})
3.4 App.vue 根组件
<!-- ClientApp/src/App.vue -->
<template>
<div id="app">
<!-- 导航栏 -->
<nav class="navbar">
<router-link to="/">首页</router-link> |
<router-link to="/about">关于</router-link> |
<router-link to="/products">产品</router-link>
</nav>
<!-- 路由视图 -->
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top: 60px;
}
.navbar {
padding: 20px;
text-align: center;
background-color: #f5f5f5;
}
.navbar a {
font-weight: bold;
color: #2c3e50;
text-decoration: none;
margin: 0 10px;
}
.navbar a.router-link-exact-active {
color: #42b983;
}
</style>
3.5 创建示例组件
<!-- ClientApp/src/views/HomeView.vue -->
<template>
<div class="home">
<h1>欢迎使用 Vue 3 + ASP.NET Core MVC</h1>
<p>这是一个集成示例</p>
<!-- 使用 Vuex 状态 -->
<div>
<p>计数器: {{ counter }}</p>
<button @click="incrementCounter">增加</button>
</div>
<!-- 调用 API 示例 -->
<div v-if="products.length > 0">
<h3>产品列表:</h3>
<ul>
<li v-for="product in products" :key="product.id">
{{ product.name }} - ¥{{ product.price }}
</li>
</ul>
</div>
<button @click="fetchProducts">获取产品</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'HomeView',
computed: {
...mapState(['counter', 'products'])
},
methods: {
...mapMutations(['increment']),
...mapActions(['fetchProducts']),
incrementCounter() {
this.increment()
}
}
}
</script>
步骤 4:创建 ASP.NET Core API 控制器
4.1 创建 ProductsController
// Controllers/Api/ProductsController.cs
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace MyVueApp.Controllers.Api
{
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
// 模拟产品数据
private static readonly List<Product> _products = new List<Product>
{
new Product { Id = 1, Name = "笔记本电脑", Price = 5999.99m, Description = "高性能笔记本电脑" },
new Product { Id = 2, Name = "智能手机", Price = 3999.99m, Description = "最新款智能手机" },
new Product { Id = 3, Name = "平板电脑", Price = 2999.99m, Description = "便携式平板电脑" }
};
// GET: api/products
[HttpGet]
public IActionResult GetProducts()
{
return Ok(_products);
}
// GET: api/products/1
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
var product = _products.Find(p => p.Id == id);
if (product == null)
return NotFound();
return Ok(product);
}
// POST: api/products
[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
if (product == null)
return BadRequest();
// 模拟生成ID
product.Id = _products.Count + 1;
_products.Add(product);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
}
// 产品模型类
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
}
}
4.2 修改 HomeController
// Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
namespace MyVueApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
// 返回主页面,Vue 应用将在此加载
return View();
}
// 其他 MVC 视图(如果需要)
public IActionResult Privacy()
{
return View();
}
// 用于服务端渲染的 API(如果需要)
[HttpGet]
public IActionResult GetServerData()
{
return Json(new { message = "来自服务器的数据", timestamp = DateTime.Now });
}
}
}
步骤 5:创建 MVC 视图
5.1 修改 Index.cshtml
<!-- Views/Home/Index.cshtml -->
@{
ViewData["Title"] = "Vue 3 + ASP.NET Core";
Layout = null; // 不使用布局页,完全由 Vue 控制
}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"]</title>
@if (Context.Request.Host.Host == "localhost")
{
<!-- 开发环境:使用 Vite 开发服务器 -->
<script type="module" src="http://localhost:3000/@vite/client"></script>
<script type="module" src="http://localhost:3000/src/main.js"></script>
}
else
{
<!-- 生产环境:使用构建后的文件 -->
<link rel="stylesheet" href="~/clientapp/assets/index.css" />
<script type="module" src="~/clientapp/assets/index.js"></script>
}
</head>
<body>
<!-- Vue 应用挂载点 -->
<div id="app"></div>
<!-- 服务器端数据(可选) -->
<script>
// 将服务器端数据传递给 Vue 应用
window.serverData = {
baseUrl: '@Url.Content("~")',
userInfo: @Html.Raw(Json.Serialize(ViewBag.UserInfo))
};
</script>
</body>
</html>
步骤 6:配置 package.json 脚本
{
"name": "my-vue-app",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"dev:full": "concurrently \"npm run dev\" \"dotnet run\"",
"build:full": "npm run build && dotnet build"
},
"dependencies": {
"vue": "^3.2.0",
"vue-router": "^4.0.0",
"vuex": "^4.0.0",
"axios": "^0.24.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.0.0",
"vite": "^2.7.0",
"concurrently": "^7.0.0"
}
}
步骤 7:创建 API 服务示例
// ClientApp/src/services/api.js
import axios from 'axios'
// 创建 axios 实例
const apiClient = axios.create({
baseURL: '/api',
headers: {
'Content-Type': 'application/json'
}
})
// 产品 API
export default {
// 获取所有产品
getProducts() {
return apiClient.get('/products')
},
// 获取单个产品
getProduct(id) {
return apiClient.get(`/products/${id}`)
},
// 创建产品
createProduct(product) {
return apiClient.post('/products', product)
}
}
步骤 8:运行和构建
8.1 开发环境运行
# 终端1:启动 Vue 开发服务器
cd ClientApp
npm run dev
# 终端2:启动 ASP.NET Core
cd ..
dotnet run
访问 https://localhost:5001 查看应用
8.2 生产环境构建
# 构建 Vue 应用
cd ClientApp
npm run build
# 构建 ASP.NET Core 应用
cd ..
dotnet publish -c Release
集成方式总结
-
开发模式:Vue 运行在独立的开发服务器(端口 3000),通过代理连接到后端 API
-
生产模式:Vue 编译为静态文件,放置在
ClientApp/dist目录,由 ASP.NET Core 静态文件中间件提供服务 -
API 通信:Vue 组件通过 Axios 调用 ASP.NET Core Web API
-
路由处理:Vue Router 处理前端路由,MVC 路由处理后端 API 和页面服务
注意事项
-
CORS 配置:如果前后端完全分离部署,需要配置 CORS
-
身份验证:可以使用 ASP.NET Core Identity 或 JWT 进行身份验证
-
服务器端渲染:如需 SSR,可以考虑使用 Vue 3 的 SSR 功能或第三方解决方案
-
热重载:开发时 Vue 组件支持热重载,提高开发效率
这种架构结合了 ASP.NET Core MVC 的强大后端能力和 Vue 3 的现代前端体验,适合需要 SEO 友好、渐进增强的应用场景。
1487

被折叠的 条评论
为什么被折叠?



