ASP.NET Core API 前后端分离跨域

环境准备

数据库: sqlserver 2022
后端:

vs2022

ASP.NET Core API

.net 8
前端:

Hbuilderx

bootstrap 5.3.0

jquery v3.7.1

bootstrap-table 1.23.5

完整项目代码下载地址

功能

实现 单张表 的 增 删 改 查

创建数据库和表

sql 复制代码
create database productDB
go
use productDB

-- 创建产品表
CREATE TABLE Products (
    ProductID INT IDENTITY(1,1) PRIMARY KEY, -- 产品ID,自增主键
    ProductName NVARCHAR(100) NOT NULL,     -- 产品名称,最大长度100字符
    Category NVARCHAR(50) NULL,             -- 产品类别,可为空
    Price DECIMAL(10, 2) NOT NULL,          -- 产品价格,保留两位小数
    Stock INT NOT NULL DEFAULT 0,           -- 库存,默认为0
    CreatedDate DATETIME NOT NULL DEFAULT GETDATE(), -- 创建时间,默认为当前时间
    IsActive BIT NOT NULL DEFAULT 1         -- 是否在售,默认在售(1)
);

搭建后台

创建Asp.Net Core API 项目



安装程序包

Microsoft.EntityFrameworkCore.Tools

Microsoft.EntityFrameworkCore.SqlServer

AutoMapper


根据数据库创建Models

在【程序包管理器控制台输入命令】

sql 复制代码
Scaffold-DbContext 'Data Source=.;Initial Catalog=productDB;User=sa;Password=123456;TrustServerCertificate=true'Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Context ProductDBContext

-OutputDir Models 输出文件夹:Models

-Context ProductDBContext DBContext类的名称

执行成功会自动创建DBContext文件和实体类文件

删除这段代码,后面会在Program.cs中注册DbContext。这里就不需要了

在appsettings.json中配置数据库连接字符串

创建dto类 和 添加automap映射配置文件

csharp 复制代码
namespace ProductDemo.Models.dto
{
    public class ProductDto
    {

        public int? ProductId { get; set; }

        public string? ProductName { get; set; } = null!;

        public string? Category { get; set; }

        public decimal? Price { get; set; } = 0;

        public int? Stock { get; set; } = 0;

        public DateTime? CreatedDate { get; set; }

        public bool? IsActive { get; set; }

    }
}
csharp 复制代码
using AutoMapper;
using ProductDemo.Models.dto;

namespace ProductDemo.Models.config
{
    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            // 从实体到 DTO 的映射
            CreateMap<Product, ProductDto>();
            CreateMap<ProductDto, Product>();
        }
    }
}

配置Program.cs

添加数据上下文对象依赖注入服务,并从appsettings.json文件中读取连接字符串配置

同时配置跨域

注册autoMap映射

csharp 复制代码
public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);

    // Add services to the container.
    

    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();

    //注册autoMap映射
    builder.Services.AddAutoMapper(typeof(MappingProfile));

    //注册DBContext
    builder.Services.AddDbContext<ProductDBContext>(option =>
    {
        option.UseSqlServer(builder.Configuration.GetConnectionString("productDB"));
    });

    //配置跨域
    builder.Services.AddCors(options =>
    {
        options.AddPolicy("cors", builder =>
        {
            builder.AllowAnyOrigin()  //允许任意主机的跨域请求
            .AllowAnyMethod() //允许任意http方法跨域请求
            .AllowAnyHeader(); //允许跨域请求包含任意请求头
        });
    });

    var app = builder.Build();

    //配置和启用cors
    app.UseCors("cors");

    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }

    app.UseAuthorization();


    app.MapControllers();

    app.Run();
}

创建API控制器

csharp 复制代码
using AutoMapper;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ProductDemo.Models;
using ProductDemo.Models.dto;
using System.Security.Cryptography;

namespace ProductDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [EnableCors("cors")]  //启用跨域
    public class ProductController : ControllerBase
    {
        //创建DBContext对象
        ProductDBContext db ;
        //创建autoMap对象
        IMapper _mapper;
        //注入DbContext
        public ProductController(ProductDBContext db,IMapper mapper)
        {
            this.db = db;
            _mapper = mapper;
        }

        /// <summary>
        /// 分页查询返回值
        /// </summary>
        /// <param name="limit">bootstrap-table默认传递的分页参数</param>
        /// <param name="offset">bootstrap-table默认传递的分页参数</param>
        /// <returns>total和rows是bootstrap-table默认需要的值</returns>
        [HttpGet("GetPageList")]
        public IActionResult GetPageList(int limit,int offset)
        {
            var total = db.Products.Count();
            var rows = db.Products.OrderBy(o=>o.ProductId).Skip(offset).Take(limit).ToList();
            return Ok(new { total = total, rows = rows });
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="product"></param>
        /// <returns></returns>
        [HttpPost("Add")]
        public IActionResult Add(ProductDto productDto)
        {
            try
            {
                //转换为实体类
                var product = _mapper.Map<Product>(productDto);
                product.CreatedDate = DateTime.Now;
                db.Products.Add(product);
                db.SaveChanges();
                return Ok(new { state = 200, message = "添加成功" });
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
            
        }

        [HttpPost("Edit")]
        public IActionResult Edit(ProductDto productDto)
        {
            //转换为实体类
            var product = _mapper.Map<Product>(productDto);
            try
            {
                var old = db.Products.Find(product.ProductId);
                if (old == null)
                {
                    return NotFound();
                }
                old.ProductName = product.ProductName;
                old.Category = product.Category;
                old.Price = product.Price;
                old.Stock = product.Stock;
                old.IsActive = product.IsActive;

                db.SaveChanges();
                return Ok(new { state = 200, message = "修改成功" });
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpGet("Delete")]
        public IActionResult Delete(int id)
        {
            try
            {
                var old = db.Products.Find(id);
                if(old == null)
                {
                    return NotFound();
                }
                db.Products.Remove(old);
                db.SaveChanges();
                return Ok(new { state = 0, message = "删除成功" });
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        

    }
}

启动API后台程序

编写前端代码

打开Hbuilder创建web项目,并下载好对应的版本

index.html

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>			
		<!-- bootstrap5.3.0 -->
		<link rel="stylesheet" href="plugins/bootstrap-5.3.0-alpha1-dist/css/bootstrap.css" />
				
		<!-- boostrap-table 1.23.5 -->
		<link rel="stylesheet" href="plugins/bootstrapTable/bootstrap-table.css" />
		
		<!-- 图标 -->
		<link rel="stylesheet" href="plugins/bootstrap-icons/bootstrap-icons.css" />

	</head>
	<body>
		<div class="container">
			<div class="toolbar">
				 <button class="btn btn-success" id="btnAdd">
					<i class="bi bi-plus-circle"></i> 添加
				</button>
			</div>
			<table  id="tab"></table>
		</div>
					
		<!-- 添加 修改模态框 -->
		<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" >
		  <div class="modal-dialog">
		    <div class="modal-content">
		      <div class="modal-header">
		        <h1 class="modal-title fs-5" id="staticBackdropLabel">编辑</h1>
		        <button type="button" class="btn-close" data-bs-dismiss="modal" ></button>
		      </div>
		      <div class="modal-body">
		        <form id="dataForm">
		          <div class="mb-3 d-none">
		            <label for="productId" class="form-label"></label>
		            <input type="text" class="form-control" name="productId" id="productId" value="0"  >
		          </div>
		          <div class="mb-3">
		            <label for="productName" class="form-label">商品名称</label>
		            <input type="text" class="form-control" name="productName" id="productName">
		          </div>
				  <div class="mb-3">
				    <label for="category" class="form-label">商品类别</label>
				    <input type="text" class="form-control" name="category" id="category">
				  </div>
				  <div class="mb-3">
				    <label for="Price" class="form-label">商品价格</label>
				    <input type="number" class="form-control" name="Price" id="Price"  value="0" >
				  </div>
				  <div class="mb-3">
				    <label for="Stock" class="form-label">商品库存</label>
				    <input type="number" class="form-control" name="Stock" id="Stock"  value="0" >
				  </div>
		          <div class="mb-3 form-check">
		            <input type="checkbox" class="form-check-input"  id="isActive" name="isActive">
		            <label class="form-check-label" for="isActive">是否启用</label>
		          </div>
		        </form>
		      </div>
		      <div class="modal-footer">
		        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
		        <button type="button" class="btn btn-primary" id="btnSave">保存</button>
		      </div>
		    </div>
		  </div>
		</div>
	</body>
	
	<!-- jquery3.7.1 -->
	<script src="js/jquery.js"></script>
	<!--获取表单并序列化-->
	<script src="js/jquery.serializejson.min.js"></script>
	
	<!-- bootstrap5.3.0 -->
	<script src="plugins/popper/poper2.11.8.min.js"></script>
	<script src="plugins/bootstrap-5.3.0-alpha1-dist/js/bootstrap.js"></script>
	
	<!-- boostrap-table 1.23.5 -->
	<script src="plugins/bootstrapTable/bootstrap-table.js"></script>
	<script src="plugins/bootstrapTable/bootstrap-table-zh-CN.js"></script>
	<script>
		$(()=>{
			$('#tab').bootstrapTable({
				url:'http://localhost:5132/api/product/GetPageList',
				pagination:true, //分页
				sidePagination: "server", //服务器分页
				pageNumber:1, 
				pageSize: 10,
				pageList: [10, 20, 50,100],
			  columns: [{
			    field: 'id',
				checkbox:true
			  },{
			    field: 'productId',
			    title: '商品id'
			  }, {
			    field: 'productName',
			    title: '商品名称'
			  }, {
			    field: 'category',
			    title: '商品类别'
			  }, {
			    field: 'price',
			    title: '商品价格'
			  }, {
			    field: 'stock',
			    title: '商品库存'
			  }, {
			    field: 'isActive',
			    title: '是否在售'
			  }, {
			    field: '',
			    title: '编辑',
				formatter:(v,r,i)=>{
					var re =  '<button class="btn btn-warning  btn-sm" οnclick="edit('+i+')">'
								+'<i class="bi bi-pencil-square"></i> 修改'
							+'</button>';
						re += 	 '&nbsp;<button class="btn btn-danger  btn-sm"  οnclick="del('+r.productId+')">'
									+'<i class="bi bi-trash"></i> 删除'
								+'</button>';
					return re;
							
				},
				
			  }]
			})
			
			//添加弹出模态框
			$("#btnAdd").on('click',()=>{
				$("#dataForm")[0].reset();
				$("#staticBackdrop").modal("show");
			});			
			
			//添加or修改
			$("#btnSave").on('click',()=>{
				//jquery.serializejson.min.js 		
				let data = $("#dataForm").serializeJSON();
				if(data.isActive){
					data.isActive=true;
				}				
				let url = "http://localhost:5132/api/product/Add";
				if(data.productId != '0'){
					url = "http://localhost:5132/api/product/Edit";
				}
				$.ajax({
					url:url,
					contentType:"application/json",
					type:"POST",
					data:JSON.stringify(data),
					success:(res)=>{
						$("#staticBackdrop").modal("hide");
						$('#tab').bootstrapTable("refresh")
					},
					error: (xhr, status, error)=> {
						console.log(error);
					}
				})
			});
			
						
		})	
			
		//编辑按钮
		function edit(i){			
			$("#dataForm")[0].reset();
			
			var row = $('#tab').bootstrapTable("getData")[i];
			$.each(row,(k,v)=>{
				if(k=="isActive"){
					 $("#" + k).prop('checked', v);
				}else{					
					$("#"+k).val(v);
				}
			});
			
			$("#staticBackdrop").modal("show");
		}
		
		//删除按钮
		function del(id){
			let data = {
				id : id
			}
			url='http://localhost:5132/api/product/Delete';
			$.ajax({
				url:url,
				contentType:"application/json",
				type:"GET",
				data:data,
				success:(res)=>{
					$('#tab').bootstrapTable("refresh")
				},
				error: (xhr, status, error)=> {
					console.log(error);
				}
			});
		}
	</script>
</html>
相关推荐
customer0843 分钟前
【开源免费】基于SpringBoot+Vue.JS加油站管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·maven
VinciYan1 小时前
C#中通过ObjectPool重用对象提高程序性能
c#·asp.net·.net·.netcore
陌上笙清净1 小时前
flask内存马的真谛!!!
后端·python·网络安全·flask
m0_748256562 小时前
Rust环境安装配置
开发语言·后端·rust
IT界的奇葩2 小时前
基于springboot使用Caffeine
java·spring boot·后端·caffeine
rookiesx2 小时前
springboot jenkins job error console log
spring boot·后端·jenkins
凡人的AI工具箱2 小时前
40分钟学 Go 语言高并发教程目录
开发语言·后端·微服务·性能优化·golang
每天写点bug3 小时前
【golang】匿名内部协程,值传递与参数传递
开发语言·后端·golang
潘多编程3 小时前
Spring Boot性能提升:实战案例分析
java·spring boot·后端