1 WebApi.Domain.Customers.Role
namespace WebApi.Domain.Customers
{
/// <summary>
/// 【角色--类】
/// <remarks>
/// 摘要:
/// 通过该实体类及其属性成员,用于实现当前程序【Core】.【领域】.【用户集】.【角色】实体与“[WebApi].[Role]”表之间的CURD的交互操作,并把这些数据存储到数据库设置实例中(内存)。
/// </remarks>
/// </summary>
public class Role
{
#region 属性
/// <summary>
/// 【编号】
/// <remarks>
/// 摘要:
/// 获取/设置所有实体实例的长整型编号值。
/// </remarks>
/// </summary>
public long Id { get; set; }
/// <summary>
/// 【角色名】
/// <remarks>
/// 摘要:
/// 获取/设置1个指定的角色名。
/// 说明:
/// 不区分大小写且必须具有唯一性。
/// </remarks>
/// </summary>
public string Name { get; set; }
/// <summary>
/// 【启用?】
/// <remarks>
/// 摘要:
/// 获取/设置1个值false(禁用)/true(默认值:启用),该值指示角色实体的1个指定实例是否处于启用状态。
/// </remarks>
/// </summary>
public bool Active { get; set; }
/// <summary>
/// 【系统角色?】
/// <remarks>
/// 摘要:
/// 获取/设置1个值false(不是系统角色)/true(默认值:系统角色),该值指示角色实体的1个指定实例是否是系统角色。
/// 说明:
/// 名称不能被修改;不能被物理/逻辑删除;必须处于启用状态。
/// </remarks>
/// </summary>
public bool IsSystemRole { get; set; }
/// <summary>
/// 【备注】
/// <remarks>
/// 摘要:
/// 获取/设置1个指定角色的备注信息。
/// </remarks>
/// </summary>
public string Remark { get; set; }
#endregion
}
}
2 WebApi.Data.EFCoreContext
using Microsoft.EntityFrameworkCore;
using WebApi.Domain.Customers;
namespace WebApi.Data
{
/// <summary>
/// 【EFCore上下文】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取/设置实体的数据库设置实例,用于实现指定实体与数据库指定表的CURD操作。
/// </remarks>
public class EFCoreContext : DbContext
{
#region 拷贝构造方法
/// <summary>
/// 【拷贝构造方法】
/// </summary>
/// <remarks>
/// 摘要:
/// 基类构造通过该构造方法中的参数实例,连接到指定数据库(SQL Server)数据库软件中数据库。
/// </remarks>
public EFCoreContext(DbContextOptions<EFCoreContext> options) : base(options)
{
//如果(SQL Server)数据库软件中没有指定的数据库, 当通过Code First模式时,在第1次生成数据库时,则通过下1行语句结合数据库连接字符串,在(SQL Server)数据库软件中生成指定的数据库数据库、表、字段和约束规则。
Database.EnsureCreated();
/*
如果(SQL Server)数据库软件中没有指定的数据库, 当通过Code First模式时,在第1次生成数据库时,则也通过下行执行迁移和更新命令行的结合数据库连接字符串,在(SQL Server)数据库软件中生成指定的数据库数据库、表、字段和约束规则。
Add-Migration Initialize(Initialize:自动生成的迁移类名,这里特指:20220803125612_Initialize.cs):
Update-Database Initialize(通过自动生成的迁移类中的定义,自动在指定的数据库软件中生成指定的数据库、表、字段和约束规则)
*/
}
#endregion
#region 属性
/// <summary>
/// 【角色数据库设置】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取/设置角色实体的数据库设置实例,用于实现当前程序【Web】.【领域】.【用户集】.【角色】实体与“[WebApi].[Role]”表之间的CURD的交互操作,并把这些数据存储到数据库设置实例中(内存)。
/// </remarks>
public DbSet<Role> RoleDbSet { get; set; }
#endregion
#region 方法--私有/保护--覆写
///<param name="builder">模型生成器实例,用于把当前程序中实体和属性所定义的约束规则,映射到数据库指定表及其字段上。</param>
/// <summary>
/// 【模型生成执行...】
/// </summary>
/// <remarks>
/// 摘要:
/// 该方法把当前程序中实体和属性所定义的约束规则,映射到数据库指定表及其字段上。
/// </remarks>
protected override void OnModelCreating(ModelBuilder builder)
{
//角色表约束规则,映射定义。
builder.Entity<Role>().ToTable(nameof(Role));
builder.Entity<Role>().HasKey(role => role.Id);
builder.Entity<Role>().Property(role => role.Name).HasMaxLength(50);
builder.Entity<Role>().Property(role => role.Remark).HasMaxLength(100);
base.OnModelCreating(builder);
}
#endregion
}
}
3 launchSettings.json
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7144;http://localhost:5083", //uView 内置路由不能通过该本机域名获取数据,“axios” 路由在浏览器中可以直获取数据,但在真/模拟机中不能获取数据。
//.Netcore IISExpress或Https在默认情况下是使用“IIS Express Development Certificate”SSL证书对“localhost”本机域名进行安全认证的,
//而该证书又不能对本机IP:127.0.0.1(IPV4)/192.168.2.230(IPV4)/::1(IPV6)进行安全认证,
//同时由于.Netcore IISExpress或Https已经使用了“IISExpress Development Certificate”SSL证书,所以通过“mkcert生成SSL证书”再对.Netcore IISExpress或Https进行安全认证后也无效,
//uView内置路由不能通过该本机域名获取数据,测试时不可以直接获取数据。
// uView 内置路由如果要想使用HTTPS协议进行测试,必须通过IIS部署实现,“axios” 路由在浏览器中可以直获取数据,在真/模拟机中也能获取数据。
//"applicationUrl": "https://127.0.0.1:7144",
//"applicationUrl": "https://192.168.1.100:7144",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
4 WebApi.Controllers.WeatherForecastController
using Microsoft.AspNetCore.Mvc;
using WebApi.Data;
using WebApi.Domain.Customers;
namespace WebApi.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
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;
private readonly EFCoreContext _eFCoreContext;
public WeatherForecastController(ILogger<WeatherForecastController> logger,
EFCoreContext eFCoreContext)
{
_logger = logger;
_eFCoreContext = eFCoreContext;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
#region CURD
[HttpGet]
public List<Role> RoleList(long? id=null)
{
if(id==null || id==0)
return _eFCoreContext.RoleDbSet.ToList();
return _eFCoreContext.RoleDbSet.Where(r=>r.Id==id).ToList();
}
[HttpPost]
public Role RolePost([FromBody] Role role)
{
//return null;//测试参数
_eFCoreContext.RoleDbSet.Add(role);
_eFCoreContext.SaveChanges();
return role;
}
[HttpPut]
public Role RolePut([FromBody] Role role)
{
//return null;//测试参数
Role _role = _eFCoreContext.RoleDbSet.FirstOrDefault(entity => entity.Id ==role.Id);
_role.Name = role.Name;
_role.IsSystemRole = role.IsSystemRole;
_role.Active = role.Active;
_role.Remark = role.Remark;
_eFCoreContext.RoleDbSet.Update(_role);
_eFCoreContext.SaveChanges();
return _role;
}
[HttpDelete]
public bool RoleDelete(long id)
{
//return null;//测试参数
Role _role = _eFCoreContext.RoleDbSet.FirstOrDefault(entity => entity.Id ==id);
_eFCoreContext.RoleDbSet.Remove(_role);
_eFCoreContext.SaveChanges();
return true;
//return _role;
}
[HttpDelete]
public bool RoleDeleteSelected([FromBody] ICollection<long> selectedIds)
{
//return null;//测试参数
var entries = _eFCoreContext.RoleDbSet.Where(entry => selectedIds.Contains(entry.Id)).ToList();
_eFCoreContext.RoleDbSet.RemoveRange(entries);
_eFCoreContext.SaveChanges();
return true;
}
/* [HttpDelete]
public Role RoleDeleteSelected(string selectedIds)
{
return null;//测试参数
}*/
#endregion CURD
}
}
5 pages\role\AxiosLocalhostRouter\AxiosLocalhostRouter.vue
<template>
<view class="content">
<u-button type="primary" @click="RoleAllById()">axios.get路由通过参数获取数据</u-button>
<u-button type="success" @click="RolePost()">axios.post路由添加数据</u-button>
<u-button type="info" @click="RolePut()">axios.put路由修改数据</u-button>
<u-button type="error" @click="RoleDelete()">axios.delete路由删除单个实例数据</u-button>
<u-button type="warning" @click="RoleDeleteSelected()">axios.delete路由删除多个实例数据</u-button>
<u-table>
<u-tr>
<u-th>编号</u-th>
<u-th>角色名</u-th>
<u-th>状态</u-th>
<u-th>系统角色</u-th>
<u-th>备注</u-th>
</u-tr>
<u-tr v-for="(item, index) in list" :key="index">
<u-td>{{ item.id }}</u-td>
<u-td>{{ item.name }}</u-td>
<u-td>{{ item.active }}</u-td>
<u-td>{{ item.isSystemRole }}</u-td>
<u-td>{{ item.remark }}</u-td>
</u-tr>
</u-table>
</view>
</template>
<script>
import axios from 'axios';
//import qs from 'qs';
export default {
data() {
return {
list: [],
}
},
async onLoad() {
//内置路由CURD测试
await this.RoleAll();
},
methods: {
async RoleAll() {
this.list = await (await axios.get('https://localhost:7144/WeatherForecast/RoleList')).data;
//console.log(".NeCore--HTTPS: localhost:7144--可用域名示例:", this.list);
},
async RoleAllById() {
let roleId = {
id: 3,
};
//axios.get路由必须包含参数关键字:params,定义格式形如:{params: roleId}。
this.list = await (await axios.get('https://localhost:7144/WeatherForecast/RoleList', {
params: roleId
})).data;
//console.log(".NeCore--HTTPS: localhost:7144--可用域名示例:", this.list);
},
async RolePost() {
let role = {
"name": "RolePost--axios.post路由",
"active": true,
"isSystemRole": true,
"remark": "axios.post路由测试"
};
//axios.post路由中的参数必须被“JSON.stringify”方法序列化,且必须包含“headers”参数实例,否则会出现错误:“AxiosError {message: 'Request failed with status code 415'”。
/* “headers” 参数实例, 可以直接定义在axios.post路由方法中(只对当前api方法有效)。
“ headers” 参数实例前端的拦截中进行定义(全局,即所有api方法有效):
config = {
baseUrl: '', // 请求的本域名
method: 'POST',
// 设置为json,返回后会对数据进行一次JSON.parse()
dataType: 'json',
showLoading: true, // 是否显示请求中的loading
loadingText: '请求中...', // 请求loading中的文字提示
loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
originalData: false, // 是否在拦截器中返回服务端的原始数据
loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
// 配置请求头信息
header: {
'content-type': 'application/json;charset=UTF-8'
},
}“
headers” 参数实例在定义在后端(全局,即所有api方法有效):
if (context.Request.Headers.ContainsKey(CorsConstants.Origin)) {
//解决在前端通过“axios.post”方式调用后端POST-API有,如果前端“axios.post”路由没有加载“headers”参数实例,下1行语句中的配置,否则“axios.post”方法,访问后端的POST-API,否则会出现:"HTTP:415"错误。
context.Request.ContentType = "application/json";
//解决在由Hbuilder创建的前端Xuni-app项目(Cors)访问当前后端项目时,浏览器或App中会出现异常:
//“' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.”。
if (context.Request.Method.Equals("OPTIONS")) {
context.Response.StatusCode = StatusCodes.Status200OK;
return;
}
}
*/
await axios.post('https://localhost:7144/WeatherForecast/RolePost',
JSON.stringify(role), {
headers: {
"Content-Type": "application/json"
}
}
);
await this.RoleAll();
},
async RolePut() {
let role = {
"id": 2,
"name": "RolePut--axios.put路由",
"active": false,
"isSystemRole": false,
"remark": "axios.put路由测试"
};
//axios.put路由中的参数必须被“JSON.stringify”方法序列化,且必须包含“headers”参数实例,否则会出现错误:“AxiosError {message: 'Request failed with status code 415'”。
/* “headers” 参数实例, 可以直接定义在axios.put路由方法中(只对当前api方法有效)。
“ headers” 参数实例前端的拦截中进行定义(全局,即所有api方法有效):
config = {
baseUrl: '', // 请求的本域名
method: 'POST',
// 设置为json,返回后会对数据进行一次JSON.parse()
dataType: 'json',
showLoading: true, // 是否显示请求中的loading
loadingText: '请求中...', // 请求loading中的文字提示
loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
originalData: false, // 是否在拦截器中返回服务端的原始数据
loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
// 配置请求头信息
header: {
'content-type': 'application/json;charset=UTF-8'
},
}“
headers” 参数实例在定义在后端(全局,即所有api方法有效):
if (context.Request.Headers.ContainsKey(CorsConstants.Origin)) {
//解决在前端通过“axios.post”方式调用后端POST-API有,如果前端“axios.post”路由没有加载“headers”参数实例,下1行语句中的配置,否则“axios.post”方法,访问后端的POST-API,否则会出现:"HTTP:415"错误。
context.Request.ContentType = "application/json";
//解决在由Hbuilder创建的前端Xuni-app项目(Cors)访问当前后端项目时,浏览器或App中会出现异常:
//“' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.”。
if (context.Request.Method.Equals("OPTIONS")) {
context.Response.StatusCode = StatusCodes.Status200OK;
return;
}
}
*/
await axios.put('https://localhost:7144/WeatherForecast/RolePut',
JSON.stringify(role), {
headers: {
"Content-Type": "application/json"
}
}
);
await this.RoleAll();
},
async RoleDelete() {
let roleId = {
id: 1
};
//axios.delete路由必须包含参数关键字:params,定义格式形如:{params: roleId}。
await axios.delete('https://localhost:7144/WeatherForecast/RoleDelete', {
params: roleId
});
await this.RoleAll();
},
async RoleDeleteSelected() {
let idArray = [2, 3, 4];
/* //后端控制器行为使用字符串类型参数实例,例如:[HttpDelete] public Role RoleDeleteSelected(string selectedIds)
let ids = {
selectedIds: idArray.join()
};
//axios.delete路由必须包含参数关键字:params,定义格式形如:{params: selectedIds}。
await axios.delete('https://localhost:7144/WeatherForecast/RoleDeleteSelected',{params: ids}); */
//后端控制器行为使用列表参数实例,例如:[HttpDelete] public IActionResult DeleteArray([FromBody] ICollection<long> selectedIds)
//注意:如果后端控制器行为使用列表参数实例,axios.delete路由的参数关键字为“data”,而非“params”,否则会出现“415”错误。
await axios.delete('https://localhost:7144/WeatherForecast/RoleDeleteSelected', { data: idArray });
await this.RoleAll();
},
}
}
</script>
<style lang="scss" scoped>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 100rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 28rpx;
color: $u-content-color;
}
.button-demo {
margin-top: 80rpx;
}
.link-demo {
margin-top: 80rpx;
}
</style>
对以上功能更为具体实现和注释见:230630_030WebApi(axios路由在uView 中的CURD实现)
230630_003uView_default(axios路由在uView 中的CURD实现)