From 28897dcb8e839f18f1f9b61939734b3b5bf2b191 Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Wed, 23 Jun 2021 17:45:21 +0800 Subject: [PATCH 01/11] =?UTF-8?q?WevApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../6.22 WebApi\347\224\237\346\210\220.md" | 53 +++++++++++++ .../6.23 WebApi-RESTful.md" | 0 .../MyApi/.vscode/launch.json" | 35 +++++++++ .../MyApi/.vscode/tasks.json" | 42 ++++++++++ .../MyApi.Api/Controllers/UsersController.cs" | 78 +++++++++++++++++++ .../Controllers/WeatherForecastController.cs" | 39 ++++++++++ .../MyApi/MyApi.Api/Entity/Users.cs" | 10 +++ .../MyApi/MyApi.Api/MyApi.Api.csproj" | 8 ++ .../MyApi/MyApi.Api/Program.cs" | 26 +++++++ .../MyApi.Api/Properties/launchSettings.json" | 30 +++++++ .../MyApi/MyApi.Api/Startup.cs" | 48 ++++++++++++ .../MyApi/MyApi.Api/WeatherForecast.cs" | 15 ++++ .../MyApi.Api/appsettings.Development.json" | 9 +++ .../MyApi/MyApi.Api/appsettings.json" | 10 +++ .../MyApi/MyApi.sln" | 34 ++++++++ .../MyApi/api.http" | 35 +++++++++ 16 files changed, 472 insertions(+) create mode 100644 "\351\273\204\345\256\207\347\205\214/6.22 WebApi\347\224\237\346\210\220.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/.vscode/launch.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/.vscode/tasks.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Program.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Properties/launchSettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/WeatherForecast.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.Development.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.sln" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/api.http" diff --git "a/\351\273\204\345\256\207\347\205\214/6.22 WebApi\347\224\237\346\210\220.md" "b/\351\273\204\345\256\207\347\205\214/6.22 WebApi\347\224\237\346\210\220.md" new file mode 100644 index 0000000..1d25b2a --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/6.22 WebApi\347\224\237\346\210\220.md" @@ -0,0 +1,53 @@ +# 使用dotnet创建webapi项目 + +``` +dotnet new 创建命令 +-n|-name 设置创建目录/文件 的名称 +add 将包或引用添加到 .NET 项目。 +sln 修改 Visual Studio 解决方案文件 +classlib 表示类库的模板 +--no-https 取消https协议 +``` + + +## 生成项目 + +1. 创建webapi解决方案 + + ``` + dotnet new sln + ``` + +2. 创建webapi项目 + + ``` + // -n 是生成项目名称 + dotnet new webapi -n 项目名 --no-https + ``` + +3. 运行项目 + + ``` + // -p 要运行的项目文件的路径(如果只有一个项目,则默认使用当前目录)。 + dotnet run -p 项目文件夹 + ``` + +4. 将项目添加到解决方案 + + ``` + dotnet sln add 项目文件夹 + ``` + + ++ 创建类库 + + ``` + dotnet new classlib -n 文件名.Entity + ``` + ++ 将项目与类库添加到解决方案中,需要指定添加到哪个解决方案 + + ``` + dotnet sln 文件名.sln add 文件名.webapi + dotnet sln 文件名.sln add 文件名.Entity + ``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" "b/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" new file mode 100644 index 0000000..e69de29 diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/launch.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/launch.json" new file mode 100644 index 0000000..5a7f77c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/launch.json" @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/MyApi.Api/bin/Debug/netcoreapp3.1/MyApi.Api.dll", + "args": [], + "cwd": "${workspaceFolder}/MyApi.Api", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/tasks.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/tasks.json" new file mode 100644 index 0000000..9d87fd9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/.vscode/tasks.json" @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" new file mode 100644 index 0000000..3cc13b1 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using MyApi.Api.Entity; +using System.Linq; + +namespace MyApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase { + [HttpGet] + // public dynamic Get(){ + // return "唯独你没懂"; + // } + + [HttpGet] + public IEnumerable Get(){ + var users = GetUsers(); + return users; + } + [HttpGet("{id}")] + public dynamic Get(int id){ + var users = GetUsers(); + var user = users.Where(x=>x.Id==id).FirstOrDefault(); + return user; + } + + + [HttpPost] + public dynamic Post(dynamic model){ + + return new{ + Data=model, + Msg="成功了" + }; + } + + [HttpPut("{id}")] + public dynamic Put(int id,dynamic model){ + + return new{ + Data=model, + Msg=string.Format("要修改的Id为{0},",id) + }; + } + + [HttpDelete("{id}")] + public dynamic Delete(int id,dynamic model){ + + return new{ + Data=model, + Msg=string.Format("要删除的Id为{0},",id) + }; + } + + + private IEnumerable GetUsers(){ + var users = new List{ + new Users{ + Id=1, + UserName="你好", + PassWord="确实好啊" + }, + new Users{ + Id=2, + UserName="真的吗", + PassWord="不啊" + }, + new Users{ + Id=3, + UserName="可以吗", + PassWord="我觉得不行" + }, + }; + return users; + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" new file mode 100644 index 0000000..06d5113 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api.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 _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" new file mode 100644 index 0000000..995f8dd --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" @@ -0,0 +1,10 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class Users{ + public int Id{get;set;} + public String UserName{get;set;} + public string PassWord{get;set;} + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" new file mode 100644 index 0000000..d12c450 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" @@ -0,0 +1,8 @@ + + + + netcoreapp3.1 + + + + diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Program.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Program.cs" new file mode 100644 index 0000000..41100d3 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Program.cs" @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Properties/launchSettings.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Properties/launchSettings.json" new file mode 100644 index 0000000..9d3877b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Properties/launchSettings.json" @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:35290", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "MyApi.Api": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" new file mode 100644 index 0000000..3e729e1 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/WeatherForecast.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/WeatherForecast.cs" new file mode 100644 index 0000000..9ee21b0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/WeatherForecast.cs" @@ -0,0 +1,15 @@ +using System; + +namespace MyApi.Api +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string Summary { get; set; } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.Development.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.Development.json" new file mode 100644 index 0000000..8983e0f --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.Development.json" @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.sln" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.sln" new file mode 100644 index 0000000..07e74c9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.sln" @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApi.Api", "MyApi.Api\MyApi.Api.csproj", "{377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" new file mode 100644 index 0000000..9fbde2b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -0,0 +1,35 @@ +###Get + +GET http://localhost:5000/users HTTP/1.1 + +### +GET http://localhost:5000/users/2 HTTP/1.1 + + +### Post + +POST http://localhost:5000/users HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"里", + "PassWord":"123" +} +### Put + +PUT http://localhost:5000/users/1 HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"这里", + "PassWord":"123" +} +### Delete + +DELETE http://localhost:5000/users/2 HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"哪里", + "PassWord":"123" +} \ No newline at end of file -- Gitee From ce6d016a539e3515bd28c94e5e676b466ee49abb Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Sat, 26 Jun 2021 17:45:18 +0800 Subject: [PATCH 02/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...45\346\225\260\346\215\256\345\272\223.md" | 29 +++++ .../\346\226\260/MyApi/.vscode/launch.json" | 35 ++++++ .../\346\226\260/MyApi/.vscode/tasks.json" | 42 +++++++ .../MyApi.Api/Controllers/UsersController.cs" | 103 ++++++++++++++++++ .../Controllers/WeatherForecastController.cs" | 39 +++++++ .../MyApi/MyApi.Api/Data/ShowDb.cs" | 13 +++ .../MyApi/MyApi.Api/Entity/Users.cs" | 18 +++ .../20210626091615_UserInfo.Designer.cs" | 50 +++++++++ .../Migrations/20210626091615_UserInfo.cs" | 33 ++++++ .../Migrations/ShowDbModelSnapshot.cs" | 48 ++++++++ .../MyApi/MyApi.Api/MyApi.Api.csproj" | 16 +++ .../MyApi/MyApi.Api/ParamModel/NewUser.cs" | 7 ++ .../\346\226\260/MyApi/MyApi.Api/Program.cs" | 26 +++++ .../MyApi.Api/Properties/launchSettings.json" | 30 +++++ .../\346\226\260/MyApi/MyApi.Api/Startup.cs" | 48 ++++++++ .../MyApi/MyApi.Api/WeatherForecast.cs" | 15 +++ .../MyApi.Api/appsettings.Development.json" | 9 ++ .../MyApi/MyApi.Api/appsettings.json" | 10 ++ .../\346\226\260/MyApi/MyApi.sln" | 34 ++++++ .../\346\226\260/MyApi/api.http" | 35 ++++++ 20 files changed, 640 insertions(+) create mode 100644 "\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" diff --git "a/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" "b/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" new file mode 100644 index 0000000..9958b0b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" @@ -0,0 +1,29 @@ +# WebApi连接数据库 + +## 安装 Entity Framework Core + +``` +// sqlserver +dotnet add package Microsoft.EntityFrameworkCore.Sqlserver + +// sqlite +dotnet add package Microsoft.EntityFrameworkCore.Sqlite +``` + +## 数据库迁移 +``` +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; + +namespace MyApi.Api.Db +{ + public class ShowDb : DbContext + { + public DbSet Users { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + } +} + +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" new file mode 100644 index 0000000..5a7f77c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/MyApi.Api/bin/Debug/netcoreapp3.1/MyApi.Api.dll", + "args": [], + "cwd": "${workspaceFolder}/MyApi.Api", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" new file mode 100644 index 0000000..9d87fd9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" new file mode 100644 index 0000000..278574a --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; + +namespace MyApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase + { + // [HttpGet] + // public dynamic Get(){ + // return "唯独你没懂"; + // } + private MyApi.Api.Db.ShowDb db = new Api.Db.ShowDb(); + + [HttpGet] + public IEnumerable Get() + { + var users = db.Users; + return users; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + return user; + } + + [HttpPost] + public dynamic Post(NewUser model) + { + var user = + new Users { + UserName = model.UserName, + PassWord = model.PassWord + }; + + db.Users.Add (user); + db.SaveChanges(); + return new { Data = user, Msg = "成功了" }; + } + + [HttpPut("{id}")] + public dynamic Put(int id, NewUser model) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + if (user != null) + { + user.UserName = model.UserName; + user.PassWord = model.PassWord; + db.Users.Update (user); + db.SaveChanges(); + return new { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + else + { + return new { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + } + + [HttpDelete("{id}")] + public dynamic Delete(int id, dynamic model) + { + return new { + Data = model, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + + private IEnumerable GetUsers() + { + var users = + new List { + new Users { + Id = 1, + UserName = "你好", + PassWord = "确实好啊" + }, + new Users { + Id = 2, + UserName = "真的吗", + PassWord = "不啊" + }, + new Users { + Id = 3, + UserName = "可以吗", + PassWord = "我觉得不行" + } + }; + return users; + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" new file mode 100644 index 0000000..06d5113 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api.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 _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" new file mode 100644 index 0000000..7adf5fa --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; + +namespace MyApi.Api.Db +{ + public class ShowDb : DbContext + { + public DbSet Users { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" new file mode 100644 index 0000000..86d3040 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" @@ -0,0 +1,18 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class Users{ + + public Users(){ + CreateTime=DateTime.Now; + UpdateTime=DateTime.Now; + } + public int Id{get;set;} + public String UserName{get;set;} + public string PassWord{get;set;} + public DateTime CreateTime{get;set;} + public DateTime UpdateTime{get;set;} + + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" new file mode 100644 index 0000000..f4b1d76 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" @@ -0,0 +1,50 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + [Migration("20210626091615_UserInfo")] + partial class UserInfo + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreateTime") + .HasColumnType("datetime2"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" new file mode 100644 index 0000000..fd1d3c7 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" @@ -0,0 +1,33 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace MyApi.Api.Migrations +{ + public partial class UserInfo : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + PassWord = table.Column(type: "nvarchar(max)", nullable: true), + CreateTime = table.Column(type: "datetime2", nullable: false), + UpdateTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" new file mode 100644 index 0000000..9963804 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" @@ -0,0 +1,48 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + partial class ShowDbModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreateTime") + .HasColumnType("datetime2"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" new file mode 100644 index 0000000..4190345 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" new file mode 100644 index 0000000..fb11a99 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" @@ -0,0 +1,7 @@ +namespace MyApi.Api.ParamModel +{ + public class NewUser{ + public string UserName{get;set;} + public string PassWord{get;set;} + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" new file mode 100644 index 0000000..41100d3 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" new file mode 100644 index 0000000..9d3877b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:35290", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "MyApi.Api": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" new file mode 100644 index 0000000..3e729e1 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" new file mode 100644 index 0000000..9ee21b0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" @@ -0,0 +1,15 @@ +using System; + +namespace MyApi.Api +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string Summary { get; set; } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" new file mode 100644 index 0000000..8983e0f --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" new file mode 100644 index 0000000..07e74c9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApi.Api", "MyApi.Api\MyApi.Api.csproj", "{377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" new file mode 100644 index 0000000..5dc2216 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" @@ -0,0 +1,35 @@ +###Get + +GET http://localhost:5000/users HTTP/1.1 + +### +GET http://localhost:5000/users/2 HTTP/1.1 + + +### Post + +POST http://localhost:5000/users HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"李白爱吃鱼", + "PassWord":"杜甫也爱" +} +### Put + +PUT http://localhost:5000/users/1 HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"这里", + "PassWord":"123" +} +### Delete + +DELETE http://localhost:5000/users/2 HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"哪里", + "PassWord":"123" +} \ No newline at end of file -- Gitee From 0a71d406efbd254b8bb391b6f335cd94debfe983 Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Sun, 27 Jun 2021 11:41:07 +0800 Subject: [PATCH 03/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../6.23 WebApi-RESTful.md" | 20 +++++++ ...45\346\225\260\346\215\256\345\272\223.md" | 53 +++++++++++++++++-- .../MyApi.Api/Controllers/UsersController.cs" | 41 ++++++++++---- .../\346\226\260/MyApi/api.http" | 17 +++--- 4 files changed, 107 insertions(+), 24 deletions(-) diff --git "a/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" "b/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" index e69de29..fcc496b 100644 --- "a/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" +++ "b/\351\273\204\345\256\207\347\205\214/6.23 WebApi-RESTful.md" @@ -0,0 +1,20 @@ +# WebApi-RESTful + +## 安装REST CLient + +VSCode 安装REST Client 插件 + +## 控制器中用法 +``` +// GET +[HttpGet("{id}")] + +// POST +[HttpPost] + +// PUT +[HttpPut("{id}")] + +// Delete +[HttpDelete("{id}")] +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" "b/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" index 9958b0b..b784b0f 100644 --- "a/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" +++ "b/\351\273\204\345\256\207\347\205\214/6.26 WebApi\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" @@ -1,4 +1,4 @@ -# WebApi连接数据库 +# WebApi 连接数据库 ## 安装 Entity Framework Core @@ -11,19 +11,66 @@ dotnet add package Microsoft.EntityFrameworkCore.Sqlite ``` ## 数据库迁移 + +``` +// 安装dotnet-ef +dotnet tool install --global dotnet-ef + +// 安装EFCore.Design +dotnet add package Microsoft.EntityFrameworkCore.Design + +// 创建迁移,指示 EF Core 创建名为 InitialCreate 的迁移 +dotnet ef migrations add InitialCreate + +// 创建数据库和架构 +dotnet ef database update ``` + +### Entity 部分配置演示 + +``` +using System; + +namespace MyApi.Api.Entity +{ + public class Users{ + + public Users(){ + CreateTime=DateTime.Now; + UpdateTime=DateTime.Now; + } + public int Id{get;set;} + public String UserName{get;set;} + public string PassWord{get;set;} + public DateTime CreateTime{get;set;} + public DateTime UpdateTime{get;set;} + } +} +``` + +### Data 部分配置演示 + +``` +// 引用EFCore using Microsoft.EntityFrameworkCore; +// 引用实体 using MyApi.Api.Entity; namespace MyApi.Api.Db { public class ShowDb : DbContext { + // 实体中的类,将要在数据库中生成的表 public DbSet Users { get; set; } + // SqlSever配置用法 protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + + // Sqlite配置用法 + // protected override void OnConfiguring(DbContextOptionsBuilder options) + // => options.UseSqlite(@"Data Source=C:\blogging.db"); + } } - -``` \ No newline at end of file +``` diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" index 278574a..c977f0a 100644 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -34,12 +34,13 @@ namespace MyApi.Api.Controllers public dynamic Post(NewUser model) { var user = - new Users { + new Users + { UserName = model.UserName, PassWord = model.PassWord }; - db.Users.Add (user); + db.Users.Add(user); db.SaveChanges(); return new { Data = user, Msg = "成功了" }; } @@ -52,29 +53,47 @@ namespace MyApi.Api.Controllers { user.UserName = model.UserName; user.PassWord = model.PassWord; - db.Users.Update (user); + db.Users.Update(user); db.SaveChanges(); - return new { + return new + { Data = user, Msg = string.Format("要修改的Id为{0},", id) }; } else { - return new { + return new + { Data = user, - Msg = string.Format("要修改的Id为{0},", id) + Msg = string.Format("找不到的Id为{0}的数据执行修改操作,", id) }; } } [HttpDelete("{id}")] - public dynamic Delete(int id, dynamic model) + public dynamic Delete(int id) { - return new { - Data = model, - Msg = string.Format("要删除的Id为{0},", id) - }; + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + + if (user != null) + { + db.Users.Remove(user); + db.SaveChanges(); + return new + { + Data = user, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + else + { + return new + { + Data = "", + Msg = string.Format("找不到的Id为{0}的数据执行删除操作,", id) + }; + } } private IEnumerable GetUsers() diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" index 5dc2216..18bac33 100644 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" @@ -1,4 +1,4 @@ -###Get +### Get获取 GET http://localhost:5000/users HTTP/1.1 @@ -6,7 +6,7 @@ GET http://localhost:5000/users HTTP/1.1 GET http://localhost:5000/users/2 HTTP/1.1 -### Post +### Post添加 POST http://localhost:5000/users HTTP/1.1 Content-Type: application/json @@ -15,7 +15,8 @@ Content-Type: application/json "UserName":"李白爱吃鱼", "PassWord":"杜甫也爱" } -### Put + +### Put修改 PUT http://localhost:5000/users/1 HTTP/1.1 Content-Type: application/json @@ -24,12 +25,8 @@ Content-Type: application/json "UserName":"这里", "PassWord":"123" } -### Delete -DELETE http://localhost:5000/users/2 HTTP/1.1 -Content-Type: application/json -{ - "UserName":"哪里", - "PassWord":"123" -} \ No newline at end of file +### Delete删除 + +DELETE http://localhost:5000/users/1 HTTP/1.1 -- Gitee From a01a45c0921971aaa186899cce385accc469ca59 Mon Sep 17 00:00:00 2001 From: YH <> Date: Tue, 29 Jun 2021 11:28:18 +0800 Subject: [PATCH 04/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...72\347\253\213\345\205\263\347\263\273.md" | 91 ++++++++++ .../MyApi/MyApi.Api/Data/ShowDb.cs" | 2 + .../MyApi/MyApi.Api/Entity/BaseEntity.cs" | 15 ++ .../MyApi/MyApi.Api/Entity/Roles.cs" | 12 ++ .../MyApi/MyApi.Api/Entity/UserRoles.cs" | 12 ++ .../MyApi/MyApi.Api/Entity/Users.cs" | 16 +- ...1\250\345\205\263\347\263\273.Designer.cs" | 159 ++++++++++++++++++ ...13\350\241\250\345\205\263\347\263\273.cs" | 104 ++++++++++++ .../Migrations/ShowDbModelSnapshot.cs" | 113 ++++++++++++- 9 files changed, 510 insertions(+), 14 deletions(-) create mode 100644 "\351\273\204\345\256\207\347\205\214/6.29 WebApi\345\260\201\350\243\205\350\241\250\345\273\272\347\253\213\345\205\263\347\263\273.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/6.29 WebApi\345\260\201\350\243\205\350\241\250\345\273\272\347\253\213\345\205\263\347\263\273.md" "b/\351\273\204\345\256\207\347\205\214/6.29 WebApi\345\260\201\350\243\205\350\241\250\345\273\272\347\253\213\345\205\263\347\263\273.md" new file mode 100644 index 0000000..1cf9211 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/6.29 WebApi\345\260\201\350\243\205\350\241\250\345\273\272\347\253\213\345\205\263\347\263\273.md" @@ -0,0 +1,91 @@ +# WebApi封装表建立关系 + +## 封装表 +``` +using System; + +namespace MyApi.Api.Entity +{ + // abstract只能被继承 + public abstract class BaseEntity + { + // 一些主要表字段 + + // Id + public int Id { get; set; } + // 是否有效 + public bool IsActived { get; set; } + // 是否删除 + public bool IsDeleted { get; set; } + // 创建时间 + public DateTime CreatedTime { get; set; } + // 删除时间 + public DateTime UpdatedTime { get; set; } + // 显示顺序 + public int DisplayOrder { get; set; } + // 备注 + public string Remarks { get; set; } + } +} +``` + +## 表关系 + +Users表 + +``` +using System; + +namespace MyApi.Api.Entity +{ + // 继承BaseEntity + public class Users:BaseEntity + { + // 用户名 + public String UserName { get; set; } + // 用户密码 + public string PassWord { get; set; } + } +} +``` + +UserRoles表 + +``` +using System; + +namespace MyApi.Api.Entity +{ + // 继承BaseEntity + public class UserRoles:BaseEntity + { + // 用户Id + public int UserId { get; set; } + // 角色Id + public int RoleId { get; set; } + + public virtual Users User { get; set; } + + public virtual Roles Role { get; set; } + } +} +``` + +Roles表 + +``` +using System; +using System.Collections.Generic; + +namespace MyApi.Api.Entity +{ + // 继承BaseEntity + public class Roles:BaseEntity + { + // 角色名称 + public string RoleName { get; set; } + + public virtual IEnumerable UserRoles { get; set; } + } +} +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" index 7adf5fa..eea082b 100644 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -6,6 +6,8 @@ namespace MyApi.Api.Db public class ShowDb : DbContext { public DbSet Users { get; set; } + public DbSet UserRoles { get; set; } + public DbSet Roles { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" new file mode 100644 index 0000000..b639c39 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" @@ -0,0 +1,15 @@ +using System; + +namespace MyApi.Api.Entity +{ + public abstract class BaseEntity + { + public int Id { get; set; } + public bool IsActived { get; set; } + public bool IsDeleted { get; set; } + public DateTime CreatedTime { get; set; } + public DateTime UpdatedTime { get; set; } + public int DisplayOrder { get; set; } + public string Remarks { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" new file mode 100644 index 0000000..b813236 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace MyApi.Api.Entity +{ + public class Roles:BaseEntity + { + public string RoleName { get; set; } + + public virtual IEnumerable UserRoles { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" new file mode 100644 index 0000000..33f6516 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" @@ -0,0 +1,12 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class UserRoles:BaseEntity + { + public int UserId { get; set; } + public int RoleId { get; set; } + public virtual Users User { get; set; } + public virtual Roles Role { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" index 86d3040..22e12b0 100644 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" @@ -2,17 +2,9 @@ using System; namespace MyApi.Api.Entity { - public class Users{ - - public Users(){ - CreateTime=DateTime.Now; - UpdateTime=DateTime.Now; - } - public int Id{get;set;} - public String UserName{get;set;} - public string PassWord{get;set;} - public DateTime CreateTime{get;set;} - public DateTime UpdateTime{get;set;} - + public class Users:BaseEntity + { + public String UserName { get; set; } + public string PassWord { get; set; } } } \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" new file mode 100644 index 0000000..28249b8 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" @@ -0,0 +1,159 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + [Migration("20210629030340_建立表关系")] + partial class 建立表关系 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.HasOne("MyApi.Api.Entity.Roles", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyApi.Api.Entity.Users", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" new file mode 100644 index 0000000..df3e1e0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" @@ -0,0 +1,104 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace MyApi.Api.Migrations +{ + public partial class 建立表关系 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleName = table.Column(type: "nvarchar(max)", nullable: true), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + PassWord = table.Column(type: "nvarchar(max)", nullable: true), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "int", nullable: false), + RoleId = table.Column(type: "int", nullable: false), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => x.Id); + table.ForeignKey( + name: "FK_UserRoles_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRoles_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + table: "UserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_UserId", + table: "UserRoles", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "Roles"); + + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" index 9963804..0e2093b 100644 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" +++ "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" @@ -19,6 +19,79 @@ namespace MyApi.Api.Migrations .HasAnnotation("ProductVersion", "5.0.7") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + modelBuilder.Entity("MyApi.Api.Entity.Users", b => { b.Property("Id") @@ -26,13 +99,25 @@ namespace MyApi.Api.Migrations .HasColumnType("int") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("CreateTime") + b.Property("CreatedTime") .HasColumnType("datetime2"); + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + b.Property("PassWord") .HasColumnType("nvarchar(max)"); - b.Property("UpdateTime") + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") .HasColumnType("datetime2"); b.Property("UserName") @@ -42,6 +127,30 @@ namespace MyApi.Api.Migrations b.ToTable("Users"); }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.HasOne("MyApi.Api.Entity.Roles", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyApi.Api.Entity.Users", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Navigation("UserRoles"); + }); #pragma warning restore 612, 618 } } -- Gitee From e30bef9364b4326e1c104ce2ecab6a647920cab5 Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Wed, 30 Jun 2021 17:28:57 +0800 Subject: [PATCH 05/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...36\345\210\240\346\224\271\346\237\245.md" | 194 ++++++++++++++++++ .../MyApi.Api/Controllers/UsersController.cs" | 153 +++++++++----- .../MyApi/MyApi.Api/Data/ShowDb.cs" | 0 .../MyApi/MyApi.Api/Entity/BaseEntity.cs" | 0 .../MyApi/MyApi.Api/Entity/Roles.cs" | 0 .../MyApi/MyApi.Api/Entity/UserRoles.cs" | 0 .../MyApi/MyApi.Api/Entity/Users.cs" | 8 +- ...1\250\345\205\263\347\263\273.Designer.cs" | 0 ...13\350\241\250\345\205\263\347\263\273.cs" | 0 .../Migrations/ShowDbModelSnapshot.cs" | 0 .../MyApi/MyApi.Api/MyApi.Api.csproj" | 8 + .../MyApi/MyApi.Api/ParamModel/NewUser.cs" | 0 .../MyApi.Api/Repository/EFRepository.cs" | 128 ++++++++++++ .../MyApi.Api/Repository/IRepository.cs" | 55 +++++ .../MyApi/api.http" | 21 +- .../\346\226\260/MyApi/.vscode/launch.json" | 35 ---- .../\346\226\260/MyApi/.vscode/tasks.json" | 42 ---- .../MyApi.Api/Controllers/UsersController.cs" | 122 ----------- .../Controllers/WeatherForecastController.cs" | 39 ---- .../MyApi/MyApi.Api/Entity/Users.cs" | 10 - .../20210626091615_UserInfo.Designer.cs" | 50 ----- .../Migrations/20210626091615_UserInfo.cs" | 33 --- .../MyApi/MyApi.Api/MyApi.Api.csproj" | 16 -- .../\346\226\260/MyApi/MyApi.Api/Program.cs" | 26 --- .../MyApi.Api/Properties/launchSettings.json" | 30 --- .../\346\226\260/MyApi/MyApi.Api/Startup.cs" | 48 ----- .../MyApi/MyApi.Api/WeatherForecast.cs" | 15 -- .../MyApi.Api/appsettings.Development.json" | 9 - .../MyApi/MyApi.Api/appsettings.json" | 10 - .../\346\226\260/MyApi/MyApi.sln" | 34 --- .../\346\226\260/MyApi/api.http" | 32 --- 31 files changed, 501 insertions(+), 617 deletions(-) create mode 100644 "\351\273\204\345\256\207\347\205\214/6.30 WebApi\345\260\201\350\243\205\346\216\245\345\217\243\345\242\236\345\210\240\346\224\271\346\237\245.md" rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/BaseEntity.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Roles.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/UserRoles.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" (100%) rename "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/NewUser.cs" (100%) create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" delete mode 100644 "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" diff --git "a/\351\273\204\345\256\207\347\205\214/6.30 WebApi\345\260\201\350\243\205\346\216\245\345\217\243\345\242\236\345\210\240\346\224\271\346\237\245.md" "b/\351\273\204\345\256\207\347\205\214/6.30 WebApi\345\260\201\350\243\205\346\216\245\345\217\243\345\242\236\345\210\240\346\224\271\346\237\245.md" new file mode 100644 index 0000000..138fbf2 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/6.30 WebApi\345\260\201\350\243\205\346\216\245\345\217\243\345\242\236\345\210\240\346\224\271\346\237\245.md" @@ -0,0 +1,194 @@ +# WebApi封装接口增删改查 + +## IRepository 配置 + +``` +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace MyApi.Api.Repository +{ + public interface IRepository + { + IQueryable Table { get; } + + /// + /// 根据Id获取指定实体 + /// + /// + /// + T GetById(int id); + + + /// + /// 使用实体对象,插入数据 + /// + /// 需要插入的对象 + void Insert(T entity); + + + /// + /// 使用实体对象,插入数据(异步) + /// + /// 需要插入的对象 + Task InsertAsync(T entity); + + + /// + /// 根据对象更新数据 + /// + /// 要更新的对象 + void Update(T entity); + + + /// + /// 根据对象更新数据(异步) + /// + /// 要更新的对象 + /// + Task UpdateAsync(T entity); + + + /// + /// 根据Id删除对应的记录 + /// + /// 主键id + void Delete(int id); + + } +} +``` + +## EFRepository配置 + +``` +using System; +using System.Threading.Tasks; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; +using MyApi.Api.Db; + +namespace MyApi.Api.Repository +{ + public class EFRepository : IRepository where T : BaseEntity + { + /// + /// 数据库上下文的变量,此处是使用常规手段,直接初始化一个数据库上下文的实例对象 + /// + /// + private ShowDb db = new ShowDb(); + + + /// + /// 一个字段成员,用于内部Entity属性 + /// + private DbSet _entity; + + + /// + /// 一个访问受限的属性,只有访问器,总是返回一个代表T类型的表对象 + /// + /// + protected DbSet Entity + { + get + { + if (_entity == null) + { + _entity = db.Set(); + } + return _entity; + } + } + + + /// + /// 代表一个可以用于查询T类型的表 + /// + /// + public IQueryable Table + { + get + { + return Entity.AsQueryable(); + } + } + + + /// + /// 删除(指定T类型,在数据库当中代表指定的表)指定Id的记录 + /// + /// + public void Delete(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + Entity.Remove(t); + db.SaveChanges(); + } + + public T GetById(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + return t; + } + + public void Insert(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + Entity.Add(entity); + db.SaveChanges(); + } + + public async Task InsertAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + await Entity.AddAsync(entity); + await db.SaveChangesAsync(); + } + + public void Update(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + db.SaveChanges(); + } + + public async Task UpdateAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + await db.SaveChangesAsync(); + } + } +} +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" index 3cc13b1..787ae95 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -1,77 +1,130 @@ -using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; -using MyApi.Api.Entity; using System.Linq; +using Microsoft.AspNetCore.Mvc; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; +using MyApi.Api.Repository; namespace MyApi.Api.Controllers { [ApiController] [Route("[controller]")] - public class UsersController : ControllerBase { - [HttpGet] - // public dynamic Get(){ - // return "唯独你没懂"; - // } + public class UsersController : ControllerBase + { + + private MyApi.Api.Db.ShowDb db = new Api.Db.ShowDb(); + private IRepository _usersReponsitory = new EFRepository(); + + [HttpGet] - public IEnumerable Get(){ - var users = GetUsers(); - return users; + public dynamic Get() + { + // var users = db.Users; + // return users; + + var users = _usersReponsitory.Table.ToList(); + return new + { + Code = 1000, + Data = users, + Msg = "获取用户列表成功!!!" + }; } + [HttpGet("{id}")] - public dynamic Get(int id){ - var users = GetUsers(); - var user = users.Where(x=>x.Id==id).FirstOrDefault(); - return user; + public dynamic Get(int id) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + return user; } - [HttpPost] - public dynamic Post(dynamic model){ + public dynamic Post(NewUser model) + { + var user = + new Users + { + UserName = model.UserName, + PassWord = model.PassWord + }; - return new{ - Data=model, - Msg="成功了" - }; + db.Users.Add(user); + db.SaveChanges(); + return new { Data = user, Msg = "成功了" }; } [HttpPut("{id}")] - public dynamic Put(int id,dynamic model){ - - return new{ - Data=model, - Msg=string.Format("要修改的Id为{0},",id) - }; + public dynamic Put(int id, NewUser model) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + if (user != null) + { + user.UserName = model.UserName; + user.PassWord = model.PassWord; + db.Users.Update(user); + db.SaveChanges(); + return new + { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + else + { + return new + { + Data = user, + Msg = string.Format("找不到的Id为{0}的数据执行修改操作,", id) + }; + } } [HttpDelete("{id}")] - public dynamic Delete(int id,dynamic model){ + public dynamic Delete(int id) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); - return new{ - Data=model, - Msg=string.Format("要删除的Id为{0},",id) - }; + if (user != null) + { + db.Users.Remove(user); + db.SaveChanges(); + return new + { + Data = user, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + else + { + return new + { + Data = "", + Msg = string.Format("找不到的Id为{0}的数据执行删除操作,", id) + }; + } } - - private IEnumerable GetUsers(){ - var users = new List{ - new Users{ - Id=1, - UserName="你好", - PassWord="确实好啊" - }, - new Users{ - Id=2, - UserName="真的吗", - PassWord="不啊" - }, - new Users{ - Id=3, - UserName="可以吗", - PassWord="我觉得不行" - }, - }; + private IEnumerable GetUsers() + { + var users = + new List { + new Users { + Id = 1, + UserName = "你好", + PassWord = "确实好啊" + }, + new Users { + Id = 2, + UserName = "真的吗", + PassWord = "不啊" + }, + new Users { + Id = 3, + UserName = "可以吗", + PassWord = "我觉得不行" + } + }; return users; } } diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Data/ShowDb.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/BaseEntity.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/BaseEntity.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/BaseEntity.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Roles.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Roles.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Roles.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/UserRoles.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/UserRoles.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/UserRoles.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" index 995f8dd..22e12b0 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/Users.cs" @@ -2,9 +2,9 @@ using System; namespace MyApi.Api.Entity { - public class Users{ - public int Id{get;set;} - public String UserName{get;set;} - public string PassWord{get;set;} + public class Users:BaseEntity + { + public String UserName { get; set; } + public string PassWord { get; set; } } } \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" index d12c450..4190345 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" @@ -4,5 +4,13 @@ netcoreapp3.1 + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/NewUser.cs" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/ParamModel/NewUser.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/NewUser.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" new file mode 100644 index 0000000..6b5403c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" @@ -0,0 +1,128 @@ +using System; +using System.Threading.Tasks; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; +using MyApi.Api.Db; + +namespace MyApi.Api.Repository +{ + public class EFRepository : IRepository where T : BaseEntity + { + /// + /// 数据库上下文的变量,此处是使用常规手段,直接初始化一个数据库上下文的实例对象 + /// + /// + private ShowDb db = new ShowDb(); + + + /// + /// 一个字段成员,用于内部Entity属性 + /// + private DbSet _entity; + + + /// + /// 一个访问受限的属性,只有访问器,总是返回一个代表T类型的表对象 + /// + /// + protected DbSet Entity + { + get + { + if (_entity == null) + { + _entity = db.Set(); + } + return _entity; + } + } + + + /// + /// 代表一个可以用于查询T类型的表 + /// + /// + public IQueryable Table + { + get + { + return Entity.AsQueryable(); + } + } + + + /// + /// 删除(指定T类型,在数据库当中代表指定的表)指定Id的记录 + /// + /// + public void Delete(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + Entity.Remove(t); + db.SaveChanges(); + } + + public T GetById(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + return t; + } + + public void Insert(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + Entity.Add(entity); + db.SaveChanges(); + } + + public async Task InsertAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + await Entity.AddAsync(entity); + await db.SaveChangesAsync(); + } + + public void Update(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + db.SaveChanges(); + } + + public async Task UpdateAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + await db.SaveChangesAsync(); + } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" new file mode 100644 index 0000000..324fb21 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace MyApi.Api.Repository +{ + public interface IRepository + { + IQueryable Table { get; } + + /// + /// 根据Id获取指定实体 + /// + /// + /// + T GetById(int id); + + + /// + /// 使用实体对象,插入数据 + /// + /// 需要插入的对象 + void Insert(T entity); + + + /// + /// 使用实体对象,插入数据(异步) + /// + /// 需要插入的对象 + Task InsertAsync(T entity); + + + /// + /// 根据对象更新数据 + /// + /// 要更新的对象 + void Update(T entity); + + + /// + /// 根据对象更新数据(异步) + /// + /// 要更新的对象 + /// + Task UpdateAsync(T entity); + + + /// + /// 根据Id删除对应的记录 + /// + /// 主键id + void Delete(int id); + + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" index 9fbde2b..18bac33 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -1,4 +1,4 @@ -###Get +### Get获取 GET http://localhost:5000/users HTTP/1.1 @@ -6,16 +6,17 @@ GET http://localhost:5000/users HTTP/1.1 GET http://localhost:5000/users/2 HTTP/1.1 -### Post +### Post添加 POST http://localhost:5000/users HTTP/1.1 Content-Type: application/json { - "UserName":"里", - "PassWord":"123" + "UserName":"李白爱吃鱼", + "PassWord":"杜甫也爱" } -### Put + +### Put修改 PUT http://localhost:5000/users/1 HTTP/1.1 Content-Type: application/json @@ -24,12 +25,8 @@ Content-Type: application/json "UserName":"这里", "PassWord":"123" } -### Delete -DELETE http://localhost:5000/users/2 HTTP/1.1 -Content-Type: application/json -{ - "UserName":"哪里", - "PassWord":"123" -} \ No newline at end of file +### Delete删除 + +DELETE http://localhost:5000/users/1 HTTP/1.1 diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" deleted file mode 100644 index 5a7f77c..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/launch.json" +++ /dev/null @@ -1,35 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "name": ".NET Core Launch (web)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/MyApi.Api/bin/Debug/netcoreapp3.1/MyApi.Api.dll", - "args": [], - "cwd": "${workspaceFolder}/MyApi.Api", - "stopAtEntry": false, - // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser - "serverReadyAction": { - "action": "openExternally", - "pattern": "\\bNow listening on:\\s+(https?://\\S+)" - }, - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "sourceFileMap": { - "/Views": "${workspaceFolder}/Views" - } - }, - { - "name": ".NET Core Attach", - "type": "coreclr", - "request": "attach" - } - ] -} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" deleted file mode 100644 index 9d87fd9..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/.vscode/tasks.json" +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "publish", - "command": "dotnet", - "type": "process", - "args": [ - "publish", - "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "watch", - "command": "dotnet", - "type": "process", - "args": [ - "watch", - "run", - "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - } - ] -} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" deleted file mode 100644 index c977f0a..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ /dev/null @@ -1,122 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Mvc; -using MyApi.Api.Entity; -using MyApi.Api.ParamModel; - -namespace MyApi.Api.Controllers -{ - [ApiController] - [Route("[controller]")] - public class UsersController : ControllerBase - { - // [HttpGet] - // public dynamic Get(){ - // return "唯独你没懂"; - // } - private MyApi.Api.Db.ShowDb db = new Api.Db.ShowDb(); - - [HttpGet] - public IEnumerable Get() - { - var users = db.Users; - return users; - } - - [HttpGet("{id}")] - public dynamic Get(int id) - { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); - return user; - } - - [HttpPost] - public dynamic Post(NewUser model) - { - var user = - new Users - { - UserName = model.UserName, - PassWord = model.PassWord - }; - - db.Users.Add(user); - db.SaveChanges(); - return new { Data = user, Msg = "成功了" }; - } - - [HttpPut("{id}")] - public dynamic Put(int id, NewUser model) - { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); - if (user != null) - { - user.UserName = model.UserName; - user.PassWord = model.PassWord; - db.Users.Update(user); - db.SaveChanges(); - return new - { - Data = user, - Msg = string.Format("要修改的Id为{0},", id) - }; - } - else - { - return new - { - Data = user, - Msg = string.Format("找不到的Id为{0}的数据执行修改操作,", id) - }; - } - } - - [HttpDelete("{id}")] - public dynamic Delete(int id) - { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); - - if (user != null) - { - db.Users.Remove(user); - db.SaveChanges(); - return new - { - Data = user, - Msg = string.Format("要删除的Id为{0},", id) - }; - } - else - { - return new - { - Data = "", - Msg = string.Format("找不到的Id为{0}的数据执行删除操作,", id) - }; - } - } - - private IEnumerable GetUsers() - { - var users = - new List { - new Users { - Id = 1, - UserName = "你好", - PassWord = "确实好啊" - }, - new Users { - Id = 2, - UserName = "真的吗", - PassWord = "不啊" - }, - new Users { - Id = 3, - UserName = "可以吗", - PassWord = "我觉得不行" - } - }; - return users; - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" deleted file mode 100644 index 06d5113..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; - -namespace MyApi.Api.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 _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet] - public IEnumerable Get() - { - var rng = new Random(); - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = rng.Next(-20, 55), - Summary = Summaries[rng.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" deleted file mode 100644 index 22e12b0..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Entity/Users.cs" +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace MyApi.Api.Entity -{ - public class Users:BaseEntity - { - public String UserName { get; set; } - public string PassWord { get; set; } - } -} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" deleted file mode 100644 index f4b1d76..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.Designer.cs" +++ /dev/null @@ -1,50 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using MyApi.Api.Db; - -namespace MyApi.Api.Migrations -{ - [DbContext(typeof(ShowDb))] - [Migration("20210626091615_UserInfo")] - partial class UserInfo - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.7") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("MyApi.Api.Entity.Users", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("CreateTime") - .HasColumnType("datetime2"); - - b.Property("PassWord") - .HasColumnType("nvarchar(max)"); - - b.Property("UpdateTime") - .HasColumnType("datetime2"); - - b.Property("UserName") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" deleted file mode 100644 index fd1d3c7..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Migrations/20210626091615_UserInfo.cs" +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace MyApi.Api.Migrations -{ - public partial class UserInfo : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserName = table.Column(type: "nvarchar(max)", nullable: true), - PassWord = table.Column(type: "nvarchar(max)", nullable: true), - CreateTime = table.Column(type: "datetime2", nullable: false), - UpdateTime = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Users"); - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" deleted file mode 100644 index 4190345..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/MyApi.Api.csproj" +++ /dev/null @@ -1,16 +0,0 @@ - - - - netcoreapp3.1 - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" deleted file mode 100644 index 41100d3..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Program.cs" +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace MyApi.Api -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" deleted file mode 100644 index 9d3877b..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Properties/launchSettings.json" +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:35290", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "weatherforecast", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "MyApi.Api": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "weatherforecast", - "applicationUrl": "http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" deleted file mode 100644 index 3e729e1..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/Startup.cs" +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace MyApi.Api -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllers(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" deleted file mode 100644 index 9ee21b0..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/WeatherForecast.cs" +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace MyApi.Api -{ - public class WeatherForecast - { - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string Summary { get; set; } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" deleted file mode 100644 index 8983e0f..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.Development.json" +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" deleted file mode 100644 index d9d9a9b..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.Api/appsettings.json" +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" -} diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" deleted file mode 100644 index 07e74c9..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/MyApi.sln" +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApi.Api", "MyApi.Api\MyApi.Api.csproj", "{377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.ActiveCfg = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.Build.0 = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.ActiveCfg = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.Build.0 = Debug|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.Build.0 = Release|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.ActiveCfg = Release|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.Build.0 = Release|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.ActiveCfg = Release|Any CPU - {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" deleted file mode 100644 index 18bac33..0000000 --- "a/\351\273\204\345\256\207\347\205\214/\346\226\260/MyApi/api.http" +++ /dev/null @@ -1,32 +0,0 @@ -### Get获取 - -GET http://localhost:5000/users HTTP/1.1 - -### -GET http://localhost:5000/users/2 HTTP/1.1 - - -### Post添加 - -POST http://localhost:5000/users HTTP/1.1 -Content-Type: application/json - -{ - "UserName":"李白爱吃鱼", - "PassWord":"杜甫也爱" -} - -### Put修改 - -PUT http://localhost:5000/users/1 HTTP/1.1 -Content-Type: application/json - -{ - "UserName":"这里", - "PassWord":"123" -} - - -### Delete删除 - -DELETE http://localhost:5000/users/1 HTTP/1.1 -- Gitee From badc103d62c7e45880f271f7ead4bafb3acc703f Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Fri, 2 Jul 2021 11:43:29 +0800 Subject: [PATCH 06/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../7.2 WebApi\345\256\271\345\231\250.md" | 337 ++++++++++++++++++ .../MyApi.Api/Controllers/UsersController.cs" | 36 +- .../MyApi/MyApi.Api/Data/ShowDb.cs" | 5 + .../MyApi.Api/Repository/EFRepository.cs" | 64 +++- .../MyApi.Api/Repository/IRepository.cs" | 19 +- .../MyApi/MyApi.Api/Startup.cs" | 7 + .../MyApi/api.http" | 4 +- .../Old/MyApi/.vscode/launch.json" | 35 ++ .../Old/MyApi/.vscode/tasks.json" | 42 +++ .../MyApi.Api/Controllers/UsersController.cs" | 131 +++++++ .../Controllers/WeatherForecastController.cs" | 39 ++ .../Old/MyApi/MyApi.Api/Data/ShowDb.cs" | 15 + .../Old/MyApi/MyApi.Api/Entity/BaseEntity.cs" | 15 + .../Old/MyApi/MyApi.Api/Entity/Roles.cs" | 12 + .../Old/MyApi/MyApi.Api/Entity/UserRoles.cs" | 12 + .../Old/MyApi/MyApi.Api/Entity/Users.cs" | 10 + ...1\250\345\205\263\347\263\273.Designer.cs" | 159 +++++++++ ...13\350\241\250\345\205\263\347\263\273.cs" | 104 ++++++ .../Migrations/ShowDbModelSnapshot.cs" | 157 ++++++++ .../Old/MyApi/MyApi.Api/MyApi.Api.csproj" | 16 + .../MyApi/MyApi.Api/ParamModel/NewUser.cs" | 7 + .../Old/MyApi/MyApi.Api/Program.cs" | 26 ++ .../MyApi.Api/Properties/launchSettings.json" | 30 ++ .../MyApi.Api/Repository/EFRepository.cs" | 128 +++++++ .../MyApi.Api/Repository/IRepository.cs" | 55 +++ .../Old/MyApi/MyApi.Api/Startup.cs" | 48 +++ .../Old/MyApi/MyApi.Api/WeatherForecast.cs" | 15 + .../MyApi.Api/appsettings.Development.json" | 9 + .../Old/MyApi/MyApi.Api/appsettings.json" | 10 + .../Old/MyApi/MyApi.sln" | 34 ++ .../Old/MyApi/api.http" | 32 ++ 31 files changed, 1583 insertions(+), 30 deletions(-) create mode 100644 "\351\273\204\345\256\207\347\205\214/7.2 WebApi\345\256\271\345\231\250.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/launch.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/tasks.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/UsersController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Data/ShowDb.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/BaseEntity.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Roles.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/UserRoles.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Users.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/MyApi.Api.csproj" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/ParamModel/NewUser.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Program.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Properties/launchSettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/EFRepository.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/IRepository.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Startup.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/WeatherForecast.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.Development.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.sln" create mode 100644 "\351\273\204\345\256\207\347\205\214/Old/MyApi/api.http" diff --git "a/\351\273\204\345\256\207\347\205\214/7.2 WebApi\345\256\271\345\231\250.md" "b/\351\273\204\345\256\207\347\205\214/7.2 WebApi\345\256\271\345\231\250.md" new file mode 100644 index 0000000..f50b54b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/7.2 WebApi\345\256\271\345\231\250.md" @@ -0,0 +1,337 @@ +# WebApi容器 + +## Startup配置 + +``` +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Repository; + +namespace MyApi.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // 注册数据库上下文到容器 + services.AddDbContext(o=>o.UseSqlServer()); + // 注册对数据库的基本操作服务到容器 + services.AddScoped(typeof(IRepository<>),typeof(EFRepository<>)); + + services.AddControllers(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} +``` + + + +# 使用容器修改 + +## Data配置 + +``` +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; + +namespace MyApi.Api.Db +{ + public class ShowDb : DbContext + { + // 因为我们使用AddDbContext到容器,所以此处必须得有带参数的构造函数(而且必须传递DbContextOptions类型的参数,同时父类也得调用这个参数) + public ShowDb(DbContextOptions options) : base(options) + { + + } + public DbSet Users { get; set; } + public DbSet UserRoles { get; set; } + public DbSet Roles { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + } +} + +``` + +## IRepository 配置 + +``` +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; + +namespace MyApi.Api.Repository +{ + public interface IRepository + { + IQueryable Table { get; } + + /// + /// 根据Id获取指定实体 + /// + /// + /// + T GetById(int id); + + + /// + /// 使用实体对象,插入数据 + /// + /// 需要插入的对象 + void Insert(T entity); + + + /// + /// 使用实体对象,插入数据(异步) + /// + /// 需要插入的对象 + Task InsertAsync(T entity); + + /// + /// 使用实体对象,插入多条数据 + /// + /// 待插入的若干实体数据 + void InsertBulk(IEnumerable entities); + /// + /// 使用实体对象,插入多条数据(异步) + /// + /// 待插入的若干实体数据 + Task InsertBulkAsync(IEnumerable entities); + + + /// + /// 根据对象更新数据 + /// + /// 要更新的对象 + void Update(T entity); + + + /// + /// 根据对象更新数据(异步) + /// + /// 要更新的若干个实体 + /// + void UpdateBulk(IEnumerable entities); + + + /// + /// 根据Id删除对应的记录 + /// + /// 主键id + void Delete(int id); + } +} +``` + +## EFRepository配置 + +``` +using System; +using System.Threading.Tasks; +using System.Linq; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; +using MyApi.Api.Db; + +namespace MyApi.Api.Repository +{ + public class EFRepository : IRepository where T : BaseEntity + { + /// + /// 数据库上下文的变量,此处是使用常规手段,直接初始化一个数据库上下文的实例对象 + /// + /// + // private ShowDb _db = new ShowDb(); + private ShowDb _db; + + public EFRepository(ShowDb db) + { + _db = db; + } + + + /// + /// 一个字段成员,用于内部Entity属性 + /// + private DbSet _entity; + + + /// + /// 一个访问受限的属性,只有访问器,总是返回一个代表T类型的表对象 + /// + /// + protected DbSet Entity + { + get + { + if (_entity == null) + { + _entity = _db.Set(); + } + return _entity; + } + } + + + /// + /// 代表一个可以用于查询T类型的表 + /// + /// + public IQueryable Table + { + get + { + return Entity.AsQueryable(); + } + } + + + /// + /// 删除(指定T类型,在数据库当中代表指定的表)指定Id的记录 + /// + /// + public void Delete(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + Entity.Remove(t); + _db.SaveChanges(); + } + + public T GetById(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + return t; + } + + public void Insert(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + Entity.Add(entity); + _db.SaveChanges(); + } + + public void InsertBulk(IEnumerable entities) + { + foreach (var entity in entities) + { + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + } + + + Entity.AddRange(entities); + _db.SaveChanges(); + } + + public async Task InsertAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + await Entity.AddAsync(entity); + await _db.SaveChangesAsync(); + } + + public async Task InsertBulkAsync(IEnumerable entities) + { + foreach (var entity in entities) + { + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + } + + + + await Entity.AddRangeAsync(entities); + await _db.SaveChangesAsync(); + } + + + public void Update(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + Entity.Update(entity); + _db.SaveChanges(); + } + + public void UpdateBulk(IEnumerable entities) + { + foreach (var entity in entities) + { + entity.UpdatedTime = DateTime.Now; + } + + _db.UpdateRange(entities); + _db.SaveChanges(); + } + } +} +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" index 787ae95..7695d30 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -12,9 +12,14 @@ namespace MyApi.Api.Controllers public class UsersController : ControllerBase { - private MyApi.Api.Db.ShowDb db = new Api.Db.ShowDb(); - private IRepository _usersReponsitory = new EFRepository(); + // private IRepository _usersRepository = new EFRepository(); + private IRepository _usersRepository; + + public UsersController(IRepository usersRepository) + { + _usersRepository=usersRepository; + } [HttpGet] @@ -23,7 +28,7 @@ namespace MyApi.Api.Controllers // var users = db.Users; // return users; - var users = _usersReponsitory.Table.ToList(); + var users = _usersRepository.Table.ToList(); return new { Code = 1000, @@ -35,7 +40,8 @@ namespace MyApi.Api.Controllers [HttpGet("{id}")] public dynamic Get(int id) { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); return user; } @@ -49,21 +55,24 @@ namespace MyApi.Api.Controllers PassWord = model.PassWord }; - db.Users.Add(user); - db.SaveChanges(); + // db.Users.Add(user); + // db.SaveChanges(); + _usersRepository.Insert(user); return new { Data = user, Msg = "成功了" }; } [HttpPut("{id}")] public dynamic Put(int id, NewUser model) { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); if (user != null) { user.UserName = model.UserName; user.PassWord = model.PassWord; - db.Users.Update(user); - db.SaveChanges(); + // db.Users.Update(user); + // db.SaveChanges(); + _usersRepository.Update(user); return new { Data = user, @@ -83,12 +92,13 @@ namespace MyApi.Api.Controllers [HttpDelete("{id}")] public dynamic Delete(int id) { - var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); - + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); if (user != null) { - db.Users.Remove(user); - db.SaveChanges(); + // db.Users.Remove(user); + // db.SaveChanges(); + _usersRepository.Delete(id); return new { Data = user, diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" index eea082b..f834ac4 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -5,6 +5,11 @@ namespace MyApi.Api.Db { public class ShowDb : DbContext { + // 因为我们使用AddDbContext到容器,所以此处必须得有带参数的构造函数(而且必须传递DbContextOptions类型的参数,同时父类也得调用这个参数) + public ShowDb(DbContextOptions options) : base(options) + { + + } public DbSet Users { get; set; } public DbSet UserRoles { get; set; } public DbSet Roles { get; set; } diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" index 6b5403c..17e9c22 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/EFRepository.cs" @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using System.Linq; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using MyApi.Api.Entity; using MyApi.Api.Db; @@ -13,7 +14,13 @@ namespace MyApi.Api.Repository /// 数据库上下文的变量,此处是使用常规手段,直接初始化一个数据库上下文的实例对象 /// /// - private ShowDb db = new ShowDb(); + // private ShowDb _db = new ShowDb(); + private ShowDb _db; + + public EFRepository(ShowDb db) + { + _db = db; + } /// @@ -32,7 +39,7 @@ namespace MyApi.Api.Repository { if (_entity == null) { - _entity = db.Set(); + _entity = _db.Set(); } return _entity; } @@ -60,7 +67,7 @@ namespace MyApi.Api.Repository { var t = Entity.Where(x => x.Id == id).FirstOrDefault(); Entity.Remove(t); - db.SaveChanges(); + _db.SaveChanges(); } public T GetById(int id) @@ -83,7 +90,23 @@ namespace MyApi.Api.Repository entity.UpdatedTime = DateTime.Now; Entity.Add(entity); - db.SaveChanges(); + _db.SaveChanges(); + } + + public void InsertBulk(IEnumerable entities) + { + foreach (var entity in entities) + { + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + } + + + Entity.AddRange(entities); + _db.SaveChanges(); } public async Task InsertAsync(T entity) @@ -100,9 +123,27 @@ namespace MyApi.Api.Repository entity.UpdatedTime = DateTime.Now; await Entity.AddAsync(entity); - await db.SaveChangesAsync(); + await _db.SaveChangesAsync(); + } + + public async Task InsertBulkAsync(IEnumerable entities) + { + foreach (var entity in entities) + { + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + } + + + + await Entity.AddRangeAsync(entities); + await _db.SaveChangesAsync(); } + public void Update(T entity) { if (entity == null) @@ -111,18 +152,19 @@ namespace MyApi.Api.Repository } entity.UpdatedTime = DateTime.Now; - db.SaveChanges(); + Entity.Update(entity); + _db.SaveChanges(); } - public async Task UpdateAsync(T entity) + public void UpdateBulk(IEnumerable entities) { - if (entity == null) + foreach (var entity in entities) { - throw new NotImplementedException(); + entity.UpdatedTime = DateTime.Now; } - entity.UpdatedTime = DateTime.Now; - await db.SaveChangesAsync(); + _db.UpdateRange(entities); + _db.SaveChanges(); } } } \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" index 324fb21..3f38e3f 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Repository/IRepository.cs" @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using System.Collections.Generic; namespace MyApi.Api.Repository { @@ -10,7 +11,7 @@ namespace MyApi.Api.Repository /// /// 根据Id获取指定实体 - /// + /// /// /// T GetById(int id); @@ -29,6 +30,17 @@ namespace MyApi.Api.Repository /// 需要插入的对象 Task InsertAsync(T entity); + /// + /// 使用实体对象,插入多条数据 + /// + /// 待插入的若干实体数据 + void InsertBulk(IEnumerable entities); + /// + /// 使用实体对象,插入多条数据(异步) + /// + /// 待插入的若干实体数据 + Task InsertBulkAsync(IEnumerable entities); + /// /// 根据对象更新数据 @@ -40,9 +52,9 @@ namespace MyApi.Api.Repository /// /// 根据对象更新数据(异步) /// - /// 要更新的对象 + /// 要更新的若干个实体 /// - Task UpdateAsync(T entity); + void UpdateBulk(IEnumerable entities); /// @@ -50,6 +62,5 @@ namespace MyApi.Api.Repository /// /// 主键id void Delete(int id); - } } \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" index 3e729e1..d140984 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" @@ -9,6 +9,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Repository; namespace MyApi.Api { @@ -24,6 +26,11 @@ namespace MyApi.Api // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + // 注册数据库上下文到容器 + services.AddDbContext(o=>o.UseSqlServer()); + // 注册对数据库的基本操作服务到容器 + services.AddScoped(typeof(IRepository<>),typeof(EFRepository<>)); + services.AddControllers(); } diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" index 18bac33..55d711e 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -18,7 +18,7 @@ Content-Type: application/json ### Put修改 -PUT http://localhost:5000/users/1 HTTP/1.1 +PUT http://localhost:5000/users/2 HTTP/1.1 Content-Type: application/json { @@ -29,4 +29,4 @@ Content-Type: application/json ### Delete删除 -DELETE http://localhost:5000/users/1 HTTP/1.1 +DELETE http://localhost:5000/users/2 HTTP/1.1 diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/launch.json" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/launch.json" new file mode 100644 index 0000000..5a7f77c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/launch.json" @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/MyApi.Api/bin/Debug/netcoreapp3.1/MyApi.Api.dll", + "args": [], + "cwd": "${workspaceFolder}/MyApi.Api", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/tasks.json" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/tasks.json" new file mode 100644 index 0000000..9d87fd9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/.vscode/tasks.json" @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/UsersController.cs" new file mode 100644 index 0000000..787ae95 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; +using MyApi.Api.Repository; + +namespace MyApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase + { + + private MyApi.Api.Db.ShowDb db = new Api.Db.ShowDb(); + private IRepository _usersReponsitory = new EFRepository(); + + + + [HttpGet] + public dynamic Get() + { + // var users = db.Users; + // return users; + + var users = _usersReponsitory.Table.ToList(); + return new + { + Code = 1000, + Data = users, + Msg = "获取用户列表成功!!!" + }; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + return user; + } + + [HttpPost] + public dynamic Post(NewUser model) + { + var user = + new Users + { + UserName = model.UserName, + PassWord = model.PassWord + }; + + db.Users.Add(user); + db.SaveChanges(); + return new { Data = user, Msg = "成功了" }; + } + + [HttpPut("{id}")] + public dynamic Put(int id, NewUser model) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + if (user != null) + { + user.UserName = model.UserName; + user.PassWord = model.PassWord; + db.Users.Update(user); + db.SaveChanges(); + return new + { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + else + { + return new + { + Data = user, + Msg = string.Format("找不到的Id为{0}的数据执行修改操作,", id) + }; + } + } + + [HttpDelete("{id}")] + public dynamic Delete(int id) + { + var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + + if (user != null) + { + db.Users.Remove(user); + db.SaveChanges(); + return new + { + Data = user, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + else + { + return new + { + Data = "", + Msg = string.Format("找不到的Id为{0}的数据执行删除操作,", id) + }; + } + } + + private IEnumerable GetUsers() + { + var users = + new List { + new Users { + Id = 1, + UserName = "你好", + PassWord = "确实好啊" + }, + new Users { + Id = 2, + UserName = "真的吗", + PassWord = "不啊" + }, + new Users { + Id = 3, + UserName = "可以吗", + PassWord = "我觉得不行" + } + }; + return users; + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" new file mode 100644 index 0000000..06d5113 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Controllers/WeatherForecastController.cs" @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api.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 _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Data/ShowDb.cs" new file mode 100644 index 0000000..eea082b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; + +namespace MyApi.Api.Db +{ + public class ShowDb : DbContext + { + public DbSet Users { get; set; } + public DbSet UserRoles { get; set; } + public DbSet Roles { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/BaseEntity.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/BaseEntity.cs" new file mode 100644 index 0000000..b639c39 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/BaseEntity.cs" @@ -0,0 +1,15 @@ +using System; + +namespace MyApi.Api.Entity +{ + public abstract class BaseEntity + { + public int Id { get; set; } + public bool IsActived { get; set; } + public bool IsDeleted { get; set; } + public DateTime CreatedTime { get; set; } + public DateTime UpdatedTime { get; set; } + public int DisplayOrder { get; set; } + public string Remarks { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Roles.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Roles.cs" new file mode 100644 index 0000000..b813236 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Roles.cs" @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace MyApi.Api.Entity +{ + public class Roles:BaseEntity + { + public string RoleName { get; set; } + + public virtual IEnumerable UserRoles { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/UserRoles.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/UserRoles.cs" new file mode 100644 index 0000000..33f6516 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/UserRoles.cs" @@ -0,0 +1,12 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class UserRoles:BaseEntity + { + public int UserId { get; set; } + public int RoleId { get; set; } + public virtual Users User { get; set; } + public virtual Roles Role { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Users.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Users.cs" new file mode 100644 index 0000000..22e12b0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Entity/Users.cs" @@ -0,0 +1,10 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class Users:BaseEntity + { + public String UserName { get; set; } + public string PassWord { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" new file mode 100644 index 0000000..28249b8 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.Designer.cs" @@ -0,0 +1,159 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + [Migration("20210629030340_建立表关系")] + partial class 建立表关系 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.HasOne("MyApi.Api.Entity.Roles", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyApi.Api.Entity.Users", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" new file mode 100644 index 0000000..df3e1e0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/20210629030340_\345\273\272\347\253\213\350\241\250\345\205\263\347\263\273.cs" @@ -0,0 +1,104 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace MyApi.Api.Migrations +{ + public partial class 建立表关系 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleName = table.Column(type: "nvarchar(max)", nullable: true), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + PassWord = table.Column(type: "nvarchar(max)", nullable: true), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "int", nullable: false), + RoleId = table.Column(type: "int", nullable: false), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => x.Id); + table.ForeignKey( + name: "FK_UserRoles_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRoles_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + table: "UserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_UserId", + table: "UserRoles", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "Roles"); + + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" new file mode 100644 index 0000000..0e2093b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" @@ -0,0 +1,157 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + partial class ShowDbModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.HasOne("MyApi.Api.Entity.Roles", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyApi.Api.Entity.Users", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/MyApi.Api.csproj" new file mode 100644 index 0000000..4190345 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/MyApi.Api.csproj" @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/ParamModel/NewUser.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/ParamModel/NewUser.cs" new file mode 100644 index 0000000..fb11a99 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/ParamModel/NewUser.cs" @@ -0,0 +1,7 @@ +namespace MyApi.Api.ParamModel +{ + public class NewUser{ + public string UserName{get;set;} + public string PassWord{get;set;} + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Program.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Program.cs" new file mode 100644 index 0000000..41100d3 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Program.cs" @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Properties/launchSettings.json" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Properties/launchSettings.json" new file mode 100644 index 0000000..9d3877b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Properties/launchSettings.json" @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:35290", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "MyApi.Api": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/EFRepository.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/EFRepository.cs" new file mode 100644 index 0000000..6b5403c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/EFRepository.cs" @@ -0,0 +1,128 @@ +using System; +using System.Threading.Tasks; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; +using MyApi.Api.Db; + +namespace MyApi.Api.Repository +{ + public class EFRepository : IRepository where T : BaseEntity + { + /// + /// 数据库上下文的变量,此处是使用常规手段,直接初始化一个数据库上下文的实例对象 + /// + /// + private ShowDb db = new ShowDb(); + + + /// + /// 一个字段成员,用于内部Entity属性 + /// + private DbSet _entity; + + + /// + /// 一个访问受限的属性,只有访问器,总是返回一个代表T类型的表对象 + /// + /// + protected DbSet Entity + { + get + { + if (_entity == null) + { + _entity = db.Set(); + } + return _entity; + } + } + + + /// + /// 代表一个可以用于查询T类型的表 + /// + /// + public IQueryable Table + { + get + { + return Entity.AsQueryable(); + } + } + + + /// + /// 删除(指定T类型,在数据库当中代表指定的表)指定Id的记录 + /// + /// + public void Delete(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + Entity.Remove(t); + db.SaveChanges(); + } + + public T GetById(int id) + { + var t = Entity.Where(x => x.Id == id).FirstOrDefault(); + return t; + } + + public void Insert(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + Entity.Add(entity); + db.SaveChanges(); + } + + public async Task InsertAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.IsActived = true; + entity.IsDeleted = false; + entity.DisplayOrder = 0; + entity.CreatedTime = DateTime.Now; + entity.UpdatedTime = DateTime.Now; + + await Entity.AddAsync(entity); + await db.SaveChangesAsync(); + } + + public void Update(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + db.SaveChanges(); + } + + public async Task UpdateAsync(T entity) + { + if (entity == null) + { + throw new NotImplementedException(); + } + + entity.UpdatedTime = DateTime.Now; + await db.SaveChangesAsync(); + } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/IRepository.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/IRepository.cs" new file mode 100644 index 0000000..324fb21 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Repository/IRepository.cs" @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace MyApi.Api.Repository +{ + public interface IRepository + { + IQueryable Table { get; } + + /// + /// 根据Id获取指定实体 + /// + /// + /// + T GetById(int id); + + + /// + /// 使用实体对象,插入数据 + /// + /// 需要插入的对象 + void Insert(T entity); + + + /// + /// 使用实体对象,插入数据(异步) + /// + /// 需要插入的对象 + Task InsertAsync(T entity); + + + /// + /// 根据对象更新数据 + /// + /// 要更新的对象 + void Update(T entity); + + + /// + /// 根据对象更新数据(异步) + /// + /// 要更新的对象 + /// + Task UpdateAsync(T entity); + + + /// + /// 根据Id删除对应的记录 + /// + /// 主键id + void Delete(int id); + + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Startup.cs" new file mode 100644 index 0000000..3e729e1 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/Startup.cs" @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace MyApi.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/WeatherForecast.cs" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/WeatherForecast.cs" new file mode 100644 index 0000000..9ee21b0 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/WeatherForecast.cs" @@ -0,0 +1,15 @@ +using System; + +namespace MyApi.Api +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string Summary { get; set; } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.Development.json" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.Development.json" new file mode 100644 index 0000000..8983e0f --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.Development.json" @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.json" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.json" new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.Api/appsettings.json" @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.sln" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.sln" new file mode 100644 index 0000000..07e74c9 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/MyApi.sln" @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApi.Api", "MyApi.Api\MyApi.Api.csproj", "{377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x64.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.ActiveCfg = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Debug|x86.Build.0 = Debug|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|Any CPU.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x64.Build.0 = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.ActiveCfg = Release|Any CPU + {377A0A24-E6C8-4A5A-A0F8-1562C9E6DAAF}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git "a/\351\273\204\345\256\207\347\205\214/Old/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/api.http" new file mode 100644 index 0000000..18bac33 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/Old/MyApi/api.http" @@ -0,0 +1,32 @@ +### Get获取 + +GET http://localhost:5000/users HTTP/1.1 + +### +GET http://localhost:5000/users/2 HTTP/1.1 + + +### Post添加 + +POST http://localhost:5000/users HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"李白爱吃鱼", + "PassWord":"杜甫也爱" +} + +### Put修改 + +PUT http://localhost:5000/users/1 HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"这里", + "PassWord":"123" +} + + +### Delete删除 + +DELETE http://localhost:5000/users/1 HTTP/1.1 -- Gitee From 3b6f83be8c10e5f20c20721480675c091a197e15 Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Sat, 3 Jul 2021 16:35:36 +0800 Subject: [PATCH 07/11] =?UTF-8?q?C#=E5=9F=BA=E7=A1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...272\347\241\200\345\233\236\351\241\276.md" | 5 +++++ .../img/csharpbasic.png" | Bin 0 -> 226112 bytes 2 files changed, 5 insertions(+) create mode 100644 "\351\273\204\345\256\207\347\205\214/7.3 C#\345\237\272\347\241\200\345\233\236\351\241\276.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/img/csharpbasic.png" diff --git "a/\351\273\204\345\256\207\347\205\214/7.3 C#\345\237\272\347\241\200\345\233\236\351\241\276.md" "b/\351\273\204\345\256\207\347\205\214/7.3 C#\345\237\272\347\241\200\345\233\236\351\241\276.md" new file mode 100644 index 0000000..fd48827 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/7.3 C#\345\237\272\347\241\200\345\233\236\351\241\276.md" @@ -0,0 +1,5 @@ +# C# 基础回顾 + +## 思维导图 + +![图片](./img/csharpbasic.png) \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/img/csharpbasic.png" "b/\351\273\204\345\256\207\347\205\214/img/csharpbasic.png" new file mode 100644 index 0000000000000000000000000000000000000000..b9aae4203a27edc850d7ff076c5882bd5c94bc87 GIT binary patch literal 226112 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�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

jclP|-#tem`(2;_s5Icf3Uh{^yi zPE#tjBO&MSGoWo6*$(xioPv${!WHUUU}5fE_@|k^rOB-5V)wqx4LB#7HWJE|gr6nZ zTu!P+LpjSqIhpsxibs{`)ldArJF&}V8A!PV6Gk9Y$U)w@OD!B9`dg;piD2AUGp5P-tOh%A zbUv*_IQwxz*VM`LUG|9{a8C)cZt}iQfvWdsKiW7|2lZw$kZ;<^q|eilP^A4Zz80Ge zbQCho3Ec^2@V9YxSBPIgHtE{|5is5`?boAH^qv5NHu(wS_@vXU;ptIeCJ}t>TOiOqkNdyjj?yz_$37g50(;&G1$^?+JVJ}g`iMR~D zQ)-PvMB#aU;v2sC39OaXTwyesY^q(v1TS_`?pmZ@<9ObCh0~+Z_1W;4&cgydoY!>n zjh)a>e)>@;Q75BX7vVYb6#+V~?6JcQAOs|r)1&9Y2&aAGlYE6jBQ8Vg`2*IRuXke5-cXLR z%|4oqPG!N>pmchV>mT>Nhlx;jErHg5`T{l>V)Ud?^0=xe?D*?^@!Y_Jju&;-*VNGA zhTC;-+IT_bX@?}T#G^)cN&28^G3EUP?}3vf7M#*hJ*=l8l6ex!($ZSLt>JbwrgeR| zN#Pi;GW&d1t7Tg=>qR&~rMnz#D$XsQ!|g}U=5ez``K9L7J>rd%RbU4%Mu`3#+9o3T^Fk+fhj1rH0d7%}b9Rvndnfn}>i9 zKG)2NYIl5k$%`7S9KSa)6}OOQ4GPC3I}HV{0*Km11y?DdL=n6-C;oc%e*Uk#1E~H! zz{~|1I~7w5dzd8BzmodtHC8!+2Qg*^O2)sC^dN^BYh3VWZS`T~5BW%S_o=Jxl~UK) zQr#(ByD4+)-LMLxr`$6Ng3jPB^lLt2<_q|eTxVfkM>Em3WTWEa717f6=9Ln3rP+?o zh_mz+H=L1n7JAp_psIX2BL*;6_X&OUmi9v`=3qta5I;>3gC zKJsH%Q+i2kq!(0U>xm+9(EaogFKpF>jWs>ml&JAIibB*4h10mNGzkHEf^aXohu*;C zLydn>Wj2hJX`G~G=*<`Q;sb3@AP$L)jU4*%Sp5&Sa^n`xHzuz~`76;XL-gdThn?ep z;P{Td8nBjG-Zej)roBB3&Gu~*On4ygY6sf8x|o_iA7OOT=9*RvqSmJ4O8$hm{1Kk| zw@q{wm3P=?B^=^=lQxOQ_)dH^7OUsj?HsNoaH}J>bHs2kzoEu1aKv)%>v@YW< zgWvcRMt302+(DcF#nZPE$AS*&s(^9bR~@7+(jO)+)>bE?yV!DyO8-*di4eGLreY;L z<6Yy7abr8c;yt+uFej&ZEE0PJcN)Vl#S`Dk?sp-x(If1su2KSel=jQ&?awrP7+#f^ z$nW4l76T7Q10&1cLXU2#l`)WwsnVpBfUDKY)qBhDXngee+I|qsAZS$jn${hk1SE_& z$@+O2ZQOI-3>M0obstq8ZE449BwQz~lt6f(^3JQpNur(u!Tfq^+)@tHks7U;MTfRv zGj=Qtb%(5lQ=Ptsgycp|^3bY~B

5RS?LS2YC;Ka?YDCpg5e3?D~xpVJ}AEnS{7c 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 literal 0 HcmV?d00001 -- Gitee From 5edd8836621a0e5394df3f0aab87fbd4a82e91ca Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Thu, 8 Jul 2021 10:40:11 +0800 Subject: [PATCH 08/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7.6 WebApi JWT\344\275\277\347\224\250.md" | 278 ++++++++++++++++++ .../MyApi.Api/Controllers/UsersController.cs" | 142 ++++++--- .../MyApi.Api/ParamModel/TokenParameter.cs" | 17 ++ .../MyApi/MyApi.Api/Utils/TokenHelper.cs" | 29 ++ .../MyApi/MyApi.Api/appsettings.json" | 8 +- .../MyApi/api.http" | 10 + 6 files changed, 440 insertions(+), 44 deletions(-) create mode 100644 "\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/TokenParameter.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Utils/TokenHelper.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" "b/\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" new file mode 100644 index 0000000..b3aff5d --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" @@ -0,0 +1,278 @@ +## JWT使用 + +appsettings.json 配置 +``` +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + + + "AllowedHosts": "*", + "tokenParameter": { + "secret": "123456123456123456", + "issuer": "YH", + "accessExpiration": 120, + "refreshExpiration": 1440 + } +} +``` + +Utils 下 TokenHelper.cs 配置 +``` +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.IdentityModel.Tokens; +using MyApi.Api.Utils; +using MyApi.Api.ParamModel; +using MyApi.Api.Entity; + +namespace MyApi.Api.Utils +{ + public class TokenHelper{ + public static string GenetateToken(TokenParameter tokenParameter,Users user){ + var claims = new[] + { + new Claim(ClaimTypes.Name, user.UserName), + new Claim(ClaimTypes.Role, "admin"), + }; + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)); + var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var jwtToken = new JwtSecurityToken(tokenParameter.Issuer, null, claims, expires: DateTime.UtcNow.AddMinutes(tokenParameter.AccessExpiration), signingCredentials: credentials); + + var token = new JwtSecurityTokenHandler().WriteToken(jwtToken); + + return token; + } + } +} +``` + +ParamModel 下 TokenParameter.cs 配置 +``` +namespace MyApi.Api.ParamModel +{ + public class TokenParameter + { + //token的密钥,不能泄露,泄露意味着所有人都可以生成你的token并且访问你的服务或者接口 + public string Secret { get; set; } + + //发行人(可以是个人或组织) + public string Issuer { get; set; } + + //token的作用时间,单位为分钟,过期后需要重新获取 + public int AccessExpiration { get; set; } + + //类似一个token的东西的作用时间,单位为分钟,用于重新获取token + public int RefreshExpiration { get; set; } + } +} +``` + +UsersController.cs 配置 +``` +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; +using MyApi.Api.Repository; +using MyApi.Api.Utils; + +namespace MyApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase + { + // private IRepository _usersRepository = new EFRepository(); + private IRepository _usersRepository; + + private TokenParameter _tokenParameter; + + private readonly IConfiguration _configuration; + + public UsersController( + IConfiguration configuration, + IRepository usersRepository + ) + { + _configuration = configuration; + _usersRepository = usersRepository; + _tokenParameter = + configuration + .GetSection("tokenParameter") + .Get(); + } + + [HttpGet] + public dynamic Get() + { + // var users = db.Users; + // return users; + var users = _usersRepository.Table.ToList(); + return new { + Code = 1000, + Data = users, + Msg = "获取用户列表成功!!!" + }; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + return new { + Code=1000, + Data = "", + Msg = "该用户不存在!!!" + }; + } + else + { + return new { + Code = 1000, + Data = user, + Msg = "获取用户列表成功!!!" + }; + } + } + + [HttpPost] + public dynamic Post(NewUser model) + { + var user = + new Users { + UserName = model.UserName, + PassWord = model.PassWord + }; + + // db.Users.Add(user); + // db.SaveChanges(); + _usersRepository.Insert (user); + return new { Data = user, Msg = "成功了" }; + } + + [HttpPut("{id}")] + public dynamic Put(int id, NewUser model) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + user.UserName = model.UserName; + user.PassWord = model.PassWord; + + // db.Users.Update(user); + // db.SaveChanges(); + _usersRepository.Update (user); + return new { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + else + { + return new { + Data = user, + Msg = + string.Format("找不到的Id为{0}的数据执行修改操作,", id) + }; + } + } + + [HttpDelete("{id}")] + public dynamic Delete(int id) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + // db.Users.Remove(user); + // db.SaveChanges(); + _usersRepository.Delete (id); + return new { + Data = user, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + else + { + return new { + Data = "", + Msg = + string.Format("找不到的Id为{0}的数据执行删除操作,", id) + }; + } + } + + [HttpPost, Route("token")] + public dynamic GetToken(NewUser model) + { + var username = model.UserName.Trim(); + var password = model.PassWord.Trim(); + + var user = + _usersRepository + .Table + .Where(x => + x.UserName == username && x.PassWord == password) + .FirstOrDefault(); + + if (user == null) + { + return new { + Code = 1001, + Data = user, + Msg = "用户名或密码不正确,请重试!!!" + }; + } + + var token = TokenHelper.GenetateToken(_tokenParameter, user); + + var res = + new { + Code = 1000, + Data = new { Token = token }, + Msg = "创建用户成功了!!!" + }; + + return res; + } + + // private IEnumerable GetUsers() + // { + // var users = + // new List { + // new Users { + // Id = 1, + // UserName = "你好", + // PassWord = "确实好啊" + // }, + // new Users { + // Id = 2, + // UserName = "真的吗", + // PassWord = "不啊" + // }, + // new Users { + // Id = 3, + // UserName = "可以吗", + // PassWord = "我觉得不行" + // } + // }; + // return users; + // } + } +} +``` \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" index 7695d30..cc90e0e 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -1,9 +1,11 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; using MyApi.Api.Entity; using MyApi.Api.ParamModel; using MyApi.Api.Repository; +using MyApi.Api.Utils; namespace MyApi.Api.Controllers { @@ -11,26 +13,33 @@ namespace MyApi.Api.Controllers [Route("[controller]")] public class UsersController : ControllerBase { - // private IRepository _usersRepository = new EFRepository(); - private IRepository _usersRepository; - public UsersController(IRepository usersRepository) + private TokenParameter _tokenParameter; + + private readonly IConfiguration _configuration; + + public UsersController( + IConfiguration configuration, + IRepository usersRepository + ) { - _usersRepository=usersRepository; + _configuration = configuration; + _usersRepository = usersRepository; + _tokenParameter = + configuration + .GetSection("tokenParameter") + .Get(); } - [HttpGet] public dynamic Get() { // var users = db.Users; // return users; - var users = _usersRepository.Table.ToList(); - return new - { + return new { Code = 1000, Data = users, Msg = "获取用户列表成功!!!" @@ -42,22 +51,36 @@ namespace MyApi.Api.Controllers { // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); var user = _usersRepository.GetById(id); - return user; + if (user != null) + { + return new { + Code=1000, + Data = "", + Msg = "该用户不存在!!!" + }; + } + else + { + return new { + Code = 1000, + Data = user, + Msg = "获取用户列表成功!!!" + }; + } } [HttpPost] public dynamic Post(NewUser model) { var user = - new Users - { + new Users { UserName = model.UserName, PassWord = model.PassWord }; // db.Users.Add(user); // db.SaveChanges(); - _usersRepository.Insert(user); + _usersRepository.Insert (user); return new { Data = user, Msg = "成功了" }; } @@ -70,21 +93,21 @@ namespace MyApi.Api.Controllers { user.UserName = model.UserName; user.PassWord = model.PassWord; + // db.Users.Update(user); // db.SaveChanges(); - _usersRepository.Update(user); - return new - { + _usersRepository.Update (user); + return new { Data = user, Msg = string.Format("要修改的Id为{0},", id) }; } else { - return new - { + return new { Data = user, - Msg = string.Format("找不到的Id为{0}的数据执行修改操作,", id) + Msg = + string.Format("找不到的Id为{0}的数据执行修改操作,", id) }; } } @@ -98,44 +121,77 @@ namespace MyApi.Api.Controllers { // db.Users.Remove(user); // db.SaveChanges(); - _usersRepository.Delete(id); - return new - { + _usersRepository.Delete (id); + return new { Data = user, Msg = string.Format("要删除的Id为{0},", id) }; } else { - return new - { + return new { Data = "", - Msg = string.Format("找不到的Id为{0}的数据执行删除操作,", id) + Msg = + string.Format("找不到的Id为{0}的数据执行删除操作,", id) }; } } - private IEnumerable GetUsers() + [HttpPost, Route("token")] + public dynamic GetToken(NewUser model) { - var users = - new List { - new Users { - Id = 1, - UserName = "你好", - PassWord = "确实好啊" - }, - new Users { - Id = 2, - UserName = "真的吗", - PassWord = "不啊" - }, - new Users { - Id = 3, - UserName = "可以吗", - PassWord = "我觉得不行" - } + var username = model.UserName.Trim(); + var password = model.PassWord.Trim(); + + var user = + _usersRepository + .Table + .Where(x => + x.UserName == username && x.PassWord == password) + .FirstOrDefault(); + + if (user == null) + { + return new { + Code = 1001, + Data = user, + Msg = "用户名或密码不正确,请重试!!!" }; - return users; + } + + var token = TokenHelper.GenetateToken(_tokenParameter, user); + + var res = + new { + Code = 1000, + Data = new { Token = token }, + Msg = "创建用户成功了!!!" + }; + + return res; } + + // private IEnumerable GetUsers() + // { + // var users = + // new List { + // new Users { + // Id = 1, + // UserName = "你好", + // PassWord = "确实好啊" + // }, + // new Users { + // Id = 2, + // UserName = "真的吗", + // PassWord = "不啊" + // }, + // new Users { + // Id = 3, + // UserName = "可以吗", + // PassWord = "我觉得不行" + // } + // }; + // return users; + // } } } diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/TokenParameter.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/TokenParameter.cs" new file mode 100644 index 0000000..1d4a915 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/ParamModel/TokenParameter.cs" @@ -0,0 +1,17 @@ +namespace MyApi.Api.ParamModel +{ + public class TokenParameter + { + //token的密钥,不能泄露,泄露意味着所有人都可以生成你的token并且访问你的服务或者接口 + public string Secret { get; set; } + + //发行人(可以是个人或组织) + public string Issuer { get; set; } + + //token的作用时间,单位为分钟,过期后需要重新获取 + public int AccessExpiration { get; set; } + + //类似一个token的东西的作用时间,单位为分钟,用于重新获取token + public int RefreshExpiration { get; set; } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Utils/TokenHelper.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Utils/TokenHelper.cs" new file mode 100644 index 0000000..81c62db --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Utils/TokenHelper.cs" @@ -0,0 +1,29 @@ +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.IdentityModel.Tokens; +using MyApi.Api.Utils; +using MyApi.Api.ParamModel; +using MyApi.Api.Entity; + +namespace MyApi.Api.Utils +{ + public class TokenHelper{ + public static string GenetateToken(TokenParameter tokenParameter,Users user){ + var claims = new[] + { + new Claim(ClaimTypes.Name, user.UserName), + new Claim(ClaimTypes.Role, "admin"), + }; + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)); + var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var jwtToken = new JwtSecurityToken(tokenParameter.Issuer, null, claims, expires: DateTime.UtcNow.AddMinutes(tokenParameter.AccessExpiration), signingCredentials: credentials); + + var token = new JwtSecurityTokenHandler().WriteToken(jwtToken); + + return token; + } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" index d9d9a9b..30307eb 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/appsettings.json" @@ -6,5 +6,11 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "tokenParameter": { + "secret": "123456123456123456", + "issuer": "YH", + "accessExpiration": 120, + "refreshExpiration": 1440 + } } diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" index 55d711e..abb010a 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -30,3 +30,13 @@ Content-Type: application/json ### Delete删除 DELETE http://localhost:5000/users/2 HTTP/1.1 + +### 登录并获取token + +POST http://localhost:5000/users/token HTTP/1.1 +Content-Type: application/json + +{ + "UserName":"李白爱吃鱼", + "PassWord":"杜甫也爱" +} \ No newline at end of file -- Gitee From 5d9e1978309b2a94653bc4df2088eb55646c286b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Jul 2021 18:03:08 +0800 Subject: [PATCH 09/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7.6 WebApi-JWT\344\275\277\347\224\250.md" | 0 ...45\345\277\227\345\256\241\350\256\241.md" | 0 .../MyApi.Api/Controllers/UsersController.cs" | 3 + .../MyApi/MyApi.Api/Data/ShowDb.cs" | 1 + .../MyApi/MyApi.Api/Entity/AuditInfo.cs" | 56 +++++ .../Filters/AuditLogActionFilter.cs" | 148 ++++++++++++ ...7\227\345\256\241\350\256\241.Designer.cs" | 225 ++++++++++++++++++ ...45\345\277\227\345\256\241\350\256\241.cs" | 47 ++++ .../Migrations/ShowDbModelSnapshot.cs" | 66 +++++ .../MyApi/MyApi.Api/MyApi.Api.csproj" | 1 + .../MyApi/MyApi.Api/Startup.cs" | 37 ++- .../MyApi/api.http" | 4 +- 12 files changed, 584 insertions(+), 4 deletions(-) rename "\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" => "\351\273\204\345\256\207\347\205\214/7.6 WebApi-JWT\344\275\277\347\224\250.md" (100%) create mode 100644 "\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/AuditInfo.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Filters/AuditLogActionFilter.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" create mode 100644 "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" diff --git "a/\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" "b/\351\273\204\345\256\207\347\205\214/7.6 WebApi-JWT\344\275\277\347\224\250.md" similarity index 100% rename from "\351\273\204\345\256\207\347\205\214/7.6 WebApi JWT\344\275\277\347\224\250.md" rename to "\351\273\204\345\256\207\347\205\214/7.6 WebApi-JWT\344\275\277\347\224\250.md" diff --git "a/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" "b/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" new file mode 100644 index 0000000..e69de29 diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" index cc90e0e..88d4af5 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using MyApi.Api.Entity; @@ -9,6 +10,7 @@ using MyApi.Api.Utils; namespace MyApi.Api.Controllers { + [Authorize] [ApiController] [Route("[controller]")] public class UsersController : ControllerBase @@ -137,6 +139,7 @@ namespace MyApi.Api.Controllers } } + [AllowAnonymous] [HttpPost, Route("token")] public dynamic GetToken(NewUser model) { diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" index f834ac4..d616876 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -13,6 +13,7 @@ namespace MyApi.Api.Db public DbSet Users { get; set; } public DbSet UserRoles { get; set; } public DbSet Roles { get; set; } + public DbSet auditInfos {get;set;} protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/AuditInfo.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/AuditInfo.cs" new file mode 100644 index 0000000..957c46d --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Entity/AuditInfo.cs" @@ -0,0 +1,56 @@ +using System; + +namespace MyApi.Api.Entity +{ + public class AuditInfo : BaseEntity + { + /// + /// 调用参数 + /// + public string Parameters { get; set; } + /// + /// 浏览器信息 + /// + public string BrowserInfo { get; set; } + /// + /// 客户端信息 + /// + public string ClientName { get; set; } + /// + /// 客户端IP地址 + /// + public string ClientIpAddress { get; set; } + /// + /// 执行耗时 + /// + public int ExecutionDuration { get; set; } + /// + /// 执行时间 + /// + public DateTime ExecutionTime { get; set; } + /// + /// 返回内容 + /// + public string ReturnValue { get; set; } + /// + /// 异常对象 + /// + public string Exception { get; set; } + /// + /// 方法名 + /// + public string MethodName { get; set; } + /// + /// 服务名 + /// + public string ServiceName { get; set; } + /// + /// 调用者信息 + /// + public string UserInfo { get; set; } + /// + /// 自定义数据 + /// + public string CustomData { get; set; } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Filters/AuditLogActionFilter.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Filters/AuditLogActionFilter.cs" new file mode 100644 index 0000000..802f38d --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Filters/AuditLogActionFilter.cs" @@ -0,0 +1,148 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using MyApi.Api.Repository; +using MyApi.Api.Entity; + +namespace AuditLogDemo.Fliters +{ + public class AuditLogActionFilter : IAsyncActionFilter + { + private readonly IRepository _auditLogService; + + public AuditLogActionFilter( + IRepository auditLogService + ) + { + _auditLogService = auditLogService; + } + + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + // 判断是否写日志 + if (!ShouldSaveAudit(context)) + { + await next(); + return; + } + //接口Type + var type = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo.AsType(); + //方法信息 + var method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; + //方法参数 + var arguments = context.ActionArguments; + //开始计时 + var stopwatch = Stopwatch.StartNew(); + var auditInfo = new AuditInfo + { + UserInfo = "浅稚", + ServiceName = type != null ? type.FullName : "", + MethodName = method.Name, + ////请求参数转Json + Parameters = JsonConvert.SerializeObject(arguments), + ExecutionTime = DateTime.Now, + BrowserInfo = context.HttpContext.Request.Headers["User-Agent"], + ClientIpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(), + //ClientName = _clientInfoProvider.ComputerName.TruncateWithPostfix(EntityDefault.FieldsLength100), + // Id = Guid.NewGuid().ToString() + }; + + ActionExecutedContext result = null; + try + { + result = await next(); + if (result.Exception != null && !result.ExceptionHandled) + { + auditInfo.Exception = result.Exception.ToString(); + } + } + catch (Exception ex) + { + auditInfo.Exception = ex.ToString(); + throw; + } + finally + { + stopwatch.Stop(); + auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds); + + if (result != null) + { + switch (result.Result) + { + case ObjectResult objectResult: + auditInfo.ReturnValue = JsonConvert.SerializeObject(objectResult.Value); + break; + + case JsonResult jsonResult: + auditInfo.ReturnValue = JsonConvert.SerializeObject(jsonResult.Value); + break; + + case ContentResult contentResult: + auditInfo.ReturnValue = contentResult.Content; + break; + } + } + Console.WriteLine(auditInfo.ToString()); + //保存审计日志 + await _auditLogService.InsertAsync(auditInfo); + } + } + + /// + /// 是否需要记录审计 + /// + /// + /// + private bool ShouldSaveAudit(ActionExecutingContext context) + { + if (!(context.ActionDescriptor is ControllerActionDescriptor)) + return false; + var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; + + if (methodInfo == null) + { + return false; + } + + if (!methodInfo.IsPublic) + { + return false; + } + + // if (methodInfo.GetCustomAttribute() != null) + // { + // return true; + // } + + // if (methodInfo.GetCustomAttribute() != null) + // { + // return false; + // } + + // var classType = methodInfo.DeclaringType; + // if (classType != null) + // { + // if (classType.GetTypeInfo().GetCustomAttribute() != null) + // { + // return true; + // } + + // if (classType.GetTypeInfo().GetCustomAttribute() != null) + // { + // return false; + // } + // } + return true; + } + } +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" new file mode 100644 index 0000000..4537c0c --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" @@ -0,0 +1,225 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyApi.Api.Db; + +namespace MyApi.Api.Migrations +{ + [DbContext(typeof(ShowDb))] + [Migration("20210708091818_日志审计")] + partial class 日志审计 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.7") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("MyApi.Api.Entity.AuditInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("BrowserInfo") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientIpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientName") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("CustomData") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Exception") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionDuration") + .HasColumnType("int"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("MethodName") + .HasColumnType("nvarchar(max)"); + + b.Property("Parameters") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("ReturnValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ServiceName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserInfo") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("auditInfos"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Users", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("PassWord") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.UserRoles", b => + { + b.HasOne("MyApi.Api.Entity.Roles", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyApi.Api.Entity.Users", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" new file mode 100644 index 0000000..f9ba0ee --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" @@ -0,0 +1,47 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace MyApi.Api.Migrations +{ + public partial class 日志审计 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "auditInfos", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Parameters = table.Column(type: "nvarchar(max)", nullable: true), + BrowserInfo = table.Column(type: "nvarchar(max)", nullable: true), + ClientName = table.Column(type: "nvarchar(max)", nullable: true), + ClientIpAddress = table.Column(type: "nvarchar(max)", nullable: true), + ExecutionDuration = table.Column(type: "int", nullable: false), + ExecutionTime = table.Column(type: "datetime2", nullable: false), + ReturnValue = table.Column(type: "nvarchar(max)", nullable: true), + Exception = table.Column(type: "nvarchar(max)", nullable: true), + MethodName = table.Column(type: "nvarchar(max)", nullable: true), + ServiceName = table.Column(type: "nvarchar(max)", nullable: true), + UserInfo = table.Column(type: "nvarchar(max)", nullable: true), + CustomData = table.Column(type: "nvarchar(max)", nullable: true), + IsActived = table.Column(type: "bit", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreatedTime = table.Column(type: "datetime2", nullable: false), + UpdatedTime = table.Column(type: "datetime2", nullable: false), + DisplayOrder = table.Column(type: "int", nullable: false), + Remarks = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_auditInfos", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "auditInfos"); + } + } +} diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" index 0e2093b..fb37c4f 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" @@ -19,6 +19,72 @@ namespace MyApi.Api.Migrations .HasAnnotation("ProductVersion", "5.0.7") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("MyApi.Api.Entity.AuditInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("BrowserInfo") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientIpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientName") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetime2"); + + b.Property("CustomData") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Exception") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionDuration") + .HasColumnType("int"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("IsActived") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("MethodName") + .HasColumnType("nvarchar(max)"); + + b.Property("Parameters") + .HasColumnType("nvarchar(max)"); + + b.Property("Remarks") + .HasColumnType("nvarchar(max)"); + + b.Property("ReturnValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ServiceName") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedTime") + .HasColumnType("datetime2"); + + b.Property("UserInfo") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("auditInfos"); + }); + modelBuilder.Entity("MyApi.Api.Entity.Roles", b => { b.Property("Id") diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" index 4190345..170d0d9 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/MyApi.Api.csproj" @@ -5,6 +5,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" index d140984..25d1c7e 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" @@ -7,10 +7,15 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.EntityFrameworkCore; using MyApi.Api.Repository; +using MyApi.Api.ParamModel; +using Microsoft.IdentityModel.Tokens; +using System.Text; +using AuditLogDemo.Fliters; namespace MyApi.Api { @@ -27,11 +32,36 @@ namespace MyApi.Api public void ConfigureServices(IServiceCollection services) { // 注册数据库上下文到容器 - services.AddDbContext(o=>o.UseSqlServer()); + services.AddDbContext(o => o.UseSqlServer()); // 注册对数据库的基本操作服务到容器 - services.AddScoped(typeof(IRepository<>),typeof(EFRepository<>)); + services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>)); + + // 注册验证器(使用何种配置来验证token) + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(option => + { + // 是否要求使用https + option.RequireHttpsMetadata=false; + // 是否保存token + option.SaveToken=true; + // 使用配置中间件,获得token的配置 + var tokenParameter=Configuration.GetSection("TokenParameter").Get(); + // 验证器的核心属性 + option.TokenValidationParameters=new TokenValidationParameters + { + ValidateIssuerSigningKey=true,//要不要验证生成token的密钥 + IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)), + ValidateIssuer=true, // 要不要验证发行token的人(个人或者组织) + ValidIssuer=tokenParameter.Issuer, + ValidateAudience=false // 是否验证受众 + }; + }); - services.AddControllers(); + services.AddControllers(options=> + { + options.Filters.Add(typeof(AuditLogActionFilter)); + }); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -44,6 +74,7 @@ namespace MyApi.Api app.UseRouting(); + app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" index abb010a..437ee93 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -1,9 +1,11 @@ ### Get获取 GET http://localhost:5000/users HTTP/1.1 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU3NDU2MzAsImlzcyI6IllIIn0.X2CZX4uVFln0IJfKSwe35iAwOP8hsYj3uU1D0JgpIkU + -### GET http://localhost:5000/users/2 HTTP/1.1 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU3NDU2MzAsImlzcyI6IllIIn0.X2CZX4uVFln0IJfKSwe35iAwOP8hsYj3uU1D0JgpIkU ### Post添加 -- Gitee From 514159c81e066e8670ec1c38b460bdfa84dfb27a Mon Sep 17 00:00:00 2001 From: YH <2543387770@qq.com> Date: Fri, 9 Jul 2021 10:06:14 +0800 Subject: [PATCH 10/11] =?UTF-8?q?WebApi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.vscode/launch.json" | 35 ++ .../.vscode/tasks.json" | 42 ++ ...45\345\277\227\345\256\241\350\256\241.md" | 541 ++++++++++++++++++ .../MyApi.Api/Controllers/UsersController.cs" | 15 +- .../MyApi/MyApi.Api/Data/ShowDb.cs" | 2 +- ...7\227\345\256\241\350\256\241.Designer.cs" | 4 +- ...45\345\277\227\345\256\241\350\256\241.cs" | 6 +- .../Migrations/ShowDbModelSnapshot.cs" | 2 +- .../MyApi/MyApi.Api/Startup.cs" | 1 + .../MyApi/api.http" | 6 +- 10 files changed, 639 insertions(+), 15 deletions(-) create mode 100644 "\351\273\204\345\256\207\347\205\214/.vscode/launch.json" create mode 100644 "\351\273\204\345\256\207\347\205\214/.vscode/tasks.json" rename "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" (98%) rename "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" => "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.cs" (94%) diff --git "a/\351\273\204\345\256\207\347\205\214/.vscode/launch.json" "b/\351\273\204\345\256\207\347\205\214/.vscode/launch.json" new file mode 100644 index 0000000..b00008a --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/.vscode/launch.json" @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/MyApi/MyApi.Api/bin/Debug/netcoreapp3.1/MyApi.Api.dll", + "args": [], + "cwd": "${workspaceFolder}/MyApi/MyApi.Api", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/.vscode/tasks.json" "b/\351\273\204\345\256\207\347\205\214/.vscode/tasks.json" new file mode 100644 index 0000000..a2a3f27 --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/.vscode/tasks.json" @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MyApi/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MyApi/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/MyApi/MyApi.Api/MyApi.Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git "a/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" "b/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" index e69de29..6cf6cfc 100644 --- "a/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" +++ "b/\351\273\204\345\256\207\347\205\214/7.8 WebApi\346\227\245\345\277\227\345\256\241\350\256\241.md" @@ -0,0 +1,541 @@ +# WebApi 日志审计 + +Entity 下 AuditInfo.cs 配置 + +``` +using System; + +namespace MyApi.Api.Entity +{ + public class AuditInfo : BaseEntity + { + /// + /// 调用参数 + /// + public string Parameters { get; set; } + /// + /// 浏览器信息 + /// + public string BrowserInfo { get; set; } + /// + /// 客户端信息 + /// + public string ClientName { get; set; } + /// + /// 客户端IP地址 + /// + public string ClientIpAddress { get; set; } + /// + /// 执行耗时 + /// + public int ExecutionDuration { get; set; } + /// + /// 执行时间 + /// + public DateTime ExecutionTime { get; set; } + /// + /// 返回内容 + /// + public string ReturnValue { get; set; } + /// + /// 异常对象 + /// + public string Exception { get; set; } + /// + /// 方法名 + /// + public string MethodName { get; set; } + /// + /// 服务名 + /// + public string ServiceName { get; set; } + /// + /// 调用者信息 + /// + public string UserInfo { get; set; } + /// + /// 自定义数据 + /// + public string CustomData { get; set; } + } +} +``` + +Data 配置 + +``` +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Entity; + +namespace MyApi.Api.Db +{ + public class ShowDb : DbContext + { + // 因为我们使用AddDbContext到容器,所以此处必须得有带参数的构造函数(而且必须传递DbContextOptions类型的参数,同时父类也得调用这个参数) + public ShowDb(DbContextOptions options) : base(options) + { + + } + public DbSet Users { get; set; } + public DbSet UserRoles { get; set; } + public DbSet Roles { get; set; } + public DbSet AuditInfos {get;set;} + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); + } +} +``` + +Filters 下 AuditLogActionFilter.cs 配置 + +``` +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using MyApi.Api.Repository; +using MyApi.Api.Entity; + +namespace AuditLogDemo.Fliters +{ + public class AuditLogActionFilter : IAsyncActionFilter + { + private readonly IRepository _auditLogService; + + public AuditLogActionFilter( + IRepository auditLogService + ) + { + _auditLogService = auditLogService; + } + + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + // 判断是否写日志 + if (!ShouldSaveAudit(context)) + { + await next(); + return; + } + //接口Type + var type = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo.AsType(); + //方法信息 + var method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; + //方法参数 + var arguments = context.ActionArguments; + //开始计时 + var stopwatch = Stopwatch.StartNew(); + var auditInfo = new AuditInfo + { + UserInfo = "浅稚", + ServiceName = type != null ? type.FullName : "", + MethodName = method.Name, + ////请求参数转Json + Parameters = JsonConvert.SerializeObject(arguments), + ExecutionTime = DateTime.Now, + BrowserInfo = context.HttpContext.Request.Headers["User-Agent"], + ClientIpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(), + //ClientName = _clientInfoProvider.ComputerName.TruncateWithPostfix(EntityDefault.FieldsLength100), + // Id = Guid.NewGuid().ToString() + }; + + ActionExecutedContext result = null; + try + { + result = await next(); + if (result.Exception != null && !result.ExceptionHandled) + { + auditInfo.Exception = result.Exception.ToString(); + } + } + catch (Exception ex) + { + auditInfo.Exception = ex.ToString(); + throw; + } + finally + { + stopwatch.Stop(); + auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds); + + if (result != null) + { + switch (result.Result) + { + case ObjectResult objectResult: + auditInfo.ReturnValue = JsonConvert.SerializeObject(objectResult.Value); + break; + + case JsonResult jsonResult: + auditInfo.ReturnValue = JsonConvert.SerializeObject(jsonResult.Value); + break; + + case ContentResult contentResult: + auditInfo.ReturnValue = contentResult.Content; + break; + } + } + Console.WriteLine(auditInfo.ToString()); + //保存审计日志 + await _auditLogService.InsertAsync(auditInfo); + } + } + + /// + /// 是否需要记录审计 + /// + /// + /// + private bool ShouldSaveAudit(ActionExecutingContext context) + { + if (!(context.ActionDescriptor is ControllerActionDescriptor)) + return false; + var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; + + if (methodInfo == null) + { + return false; + } + + if (!methodInfo.IsPublic) + { + return false; + } + + // if (methodInfo.GetCustomAttribute() != null) + // { + // return true; + // } + + // if (methodInfo.GetCustomAttribute() != null) + // { + // return false; + // } + + // var classType = methodInfo.DeclaringType; + // if (classType != null) + // { + // if (classType.GetTypeInfo().GetCustomAttribute() != null) + // { + // return true; + // } + + // if (classType.GetTypeInfo().GetCustomAttribute() != null) + // { + // return false; + // } + // } + return true; + } + } +} +``` + +Controllers 下 UsersController.cs 配置 + +``` +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; +using MyApi.Api.Repository; +using MyApi.Api.Utils; + + +namespace MyApi.Api.Controllers +{ + [Authorize] + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase + { + // private IRepository _usersRepository = new EFRepository(); + private IRepository _usersRepository; + + private TokenParameter _tokenParameter; + + private readonly IConfiguration _configuration; + + public UsersController( + IConfiguration configuration, + IRepository usersRepository + ) + { + _configuration = configuration; + _usersRepository = usersRepository; + _tokenParameter = + configuration + .GetSection("tokenParameter") + .Get(); + } + + [HttpGet] + public dynamic Get() + { + // var users = db.Users; + // return users; + var users = _usersRepository.Table.ToList(); + return new { + Code = 1000, + Data = users, + Msg = "获取用户列表成功!!!" + }; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + return new { + Code = 1000, + Data = user, + Msg = "获取用户列表成功!!!" + }; + } + else + { + return new { + Code=1000, + Data = "", + Msg = "该用户不存在!!!" + }; + } + } + + [AllowAnonymous] + [HttpPost] + public dynamic Post(NewUser model) + { + var user = + new Users { + UserName = model.UserName, + PassWord = model.PassWord + }; + + // db.Users.Add(user); + // db.SaveChanges(); + _usersRepository.Insert (user); + return new { Data = user, Msg = "成功了" }; + } + + [AllowAnonymous] + [HttpPut("{id}")] + public dynamic Put(int id, NewUser model) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + user.UserName = model.UserName; + user.PassWord = model.PassWord; + + // db.Users.Update(user); + // db.SaveChanges(); + _usersRepository.Update (user); + return new { + Data = user, + Msg = string.Format("要修改的Id为{0},", id) + }; + } + else + { + return new { + Data = user, + Msg = + string.Format("找不到的Id为{0}的数据执行修改操作,", id) + }; + } + } + + [HttpDelete("{id}")] + public dynamic Delete(int id) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user = _usersRepository.GetById(id); + if (user != null) + { + // db.Users.Remove(user); + // db.SaveChanges(); + _usersRepository.Delete (id); + return new { + Data = user, + Msg = string.Format("要删除的Id为{0},", id) + }; + } + else + { + return new { + Data = "", + Msg = + string.Format("找不到的Id为{0}的数据执行删除操作,", id) + }; + } + } + + [AllowAnonymous] + [HttpPost, Route("token")] + public dynamic GetToken(NewUser model) + { + var username = model.UserName.Trim(); + var password = model.PassWord.Trim(); + + var user = + _usersRepository + .Table + .Where(x => + x.UserName == username && x.PassWord == password) + .FirstOrDefault(); + + if (user == null) + { + return new { + Code = 1001, + Data = user, + Msg = "用户名或密码不正确,请重试!!!" + }; + } + + var token = TokenHelper.GenetateToken(_tokenParameter, user); + + var res = + new { + Code = 1000, + Data = new { Token = token }, + Msg = "创建用户成功了!!!" + }; + + return res; + } + + // private IEnumerable GetUsers() + // { + // var users = + // new List { + // new Users { + // Id = 1, + // UserName = "你好", + // PassWord = "确实好啊" + // }, + // new Users { + // Id = 2, + // UserName = "真的吗", + // PassWord = "不啊" + // }, + // new Users { + // Id = 3, + // UserName = "可以吗", + // PassWord = "我觉得不行" + // } + // }; + // return users; + // } + } +} +``` + +Startup.cs 配置 + +``` +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.EntityFrameworkCore; +using MyApi.Api.Repository; +using MyApi.Api.ParamModel; +using Microsoft.IdentityModel.Tokens; +using System.Text; +using AuditLogDemo.Fliters; + +namespace MyApi.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // 注册数据库上下文到容器 + services.AddDbContext(o => o.UseSqlServer()); + // 注册对数据库的基本操作服务到容器 + services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>)); + + // 注册验证器(使用何种配置来验证token) + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(option => + { + // 是否要求使用https + option.RequireHttpsMetadata=false; + // 是否保存token + option.SaveToken=true; + // 使用配置中间件,获得token的配置 + var tokenParameter=Configuration.GetSection("TokenParameter").Get(); + // 验证器的核心属性 + option.TokenValidationParameters=new TokenValidationParameters + { + ValidateIssuerSigningKey=true,//要不要验证生成token的密钥 + IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)), + ValidateIssuer=true, // 要不要验证发行token的人(个人或者组织) + ValidIssuer=tokenParameter.Issuer, + ValidateAudience=false // 是否验证受众 + }; + }); + + services.AddControllers(options=> + { + options.Filters.Add(typeof(AuditLogActionFilter)); + }); + + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + // 将token的验证注册到中间件 + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} +``` diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" index 88d4af5..1e71930 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Controllers/UsersController.cs" @@ -8,6 +8,7 @@ using MyApi.Api.ParamModel; using MyApi.Api.Repository; using MyApi.Api.Utils; + namespace MyApi.Api.Controllers { [Authorize] @@ -56,21 +57,22 @@ namespace MyApi.Api.Controllers if (user != null) { return new { - Code=1000, - Data = "", - Msg = "该用户不存在!!!" + Code = 1000, + Data = user, + Msg = "获取用户列表成功!!!" }; } else { return new { - Code = 1000, - Data = user, - Msg = "获取用户列表成功!!!" + Code=1000, + Data = "", + Msg = "该用户不存在!!!" }; } } + [AllowAnonymous] [HttpPost] public dynamic Post(NewUser model) { @@ -86,6 +88,7 @@ namespace MyApi.Api.Controllers return new { Data = user, Msg = "成功了" }; } + [AllowAnonymous] [HttpPut("{id}")] public dynamic Put(int id, NewUser model) { diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" index d616876..9ba8b64 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Data/ShowDb.cs" @@ -13,7 +13,7 @@ namespace MyApi.Api.Db public DbSet Users { get; set; } public DbSet UserRoles { get; set; } public DbSet Roles { get; set; } - public DbSet auditInfos {get;set;} + public DbSet AuditInfos {get;set;} protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlServer(@"server=.;database=ShowDb;uid=sa;pwd=123456;"); diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" similarity index 98% rename from "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" index 4537c0c..a5e6554 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.Designer.cs" @@ -10,7 +10,7 @@ using MyApi.Api.Db; namespace MyApi.Api.Migrations { [DbContext(typeof(ShowDb))] - [Migration("20210708091818_日志审计")] + [Migration("20210709013045_日志审计")] partial class 日志审计 { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -84,7 +84,7 @@ namespace MyApi.Api.Migrations b.HasKey("Id"); - b.ToTable("auditInfos"); + b.ToTable("AuditInfos"); }); modelBuilder.Entity("MyApi.Api.Entity.Roles", b => diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.cs" similarity index 94% rename from "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" rename to "\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.cs" index f9ba0ee..1610286 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210708091818_\346\227\245\345\277\227\345\256\241\350\256\241.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/20210709013045_\346\227\245\345\277\227\345\256\241\350\256\241.cs" @@ -8,7 +8,7 @@ namespace MyApi.Api.Migrations protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "auditInfos", + name: "AuditInfos", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -34,14 +34,14 @@ namespace MyApi.Api.Migrations }, constraints: table => { - table.PrimaryKey("PK_auditInfos", x => x.Id); + table.PrimaryKey("PK_AuditInfos", x => x.Id); }); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "auditInfos"); + name: "AuditInfos"); } } } diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" index fb37c4f..d28c3ce 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Migrations/ShowDbModelSnapshot.cs" @@ -82,7 +82,7 @@ namespace MyApi.Api.Migrations b.HasKey("Id"); - b.ToTable("auditInfos"); + b.ToTable("AuditInfos"); }); modelBuilder.Entity("MyApi.Api.Entity.Roles", b => diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" index 25d1c7e..3d35516 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/MyApi.Api/Startup.cs" @@ -74,6 +74,7 @@ namespace MyApi.Api app.UseRouting(); + // 将token的验证注册到中间件 app.UseAuthentication(); app.UseAuthorization(); diff --git "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" index 437ee93..9f61cfa 100644 --- "a/\351\273\204\345\256\207\347\205\214/MyApi/api.http" +++ "b/\351\273\204\345\256\207\347\205\214/MyApi/api.http" @@ -1,11 +1,12 @@ ### Get获取 GET http://localhost:5000/users HTTP/1.1 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU3NDU2MzAsImlzcyI6IllIIn0.X2CZX4uVFln0IJfKSwe35iAwOP8hsYj3uU1D0JgpIkU +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU4MDA4NDQsImlzcyI6IllIIn0.Sx5i2adWo95BN2QPjL1rRIHWDRMGngiCvBKUDEUdR7g +### Get获取指定用户信息 GET http://localhost:5000/users/2 HTTP/1.1 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU3NDU2MzAsImlzcyI6IllIIn0.X2CZX4uVFln0IJfKSwe35iAwOP8hsYj3uU1D0JgpIkU +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU4MDA4NDQsImlzcyI6IllIIn0.Sx5i2adWo95BN2QPjL1rRIHWDRMGngiCvBKUDEUdR7g ### Post添加 @@ -32,6 +33,7 @@ Content-Type: application/json ### Delete删除 DELETE http://localhost:5000/users/2 HTTP/1.1 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi5p2O55m954ix5ZCD6bG8IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJleHAiOjE2MjU4MDA4NDQsImlzcyI6IllIIn0.Sx5i2adWo95BN2QPjL1rRIHWDRMGngiCvBKUDEUdR7g ### 登录并获取token -- Gitee From cabaf2455e90c0ac04281a84d9eb6673c791f226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AE=87=E7=85=8C?= <2543387770@qq.com> Date: Sat, 10 Jul 2021 17:41:46 +0800 Subject: [PATCH 11/11] =?UTF-8?q?Vue=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...75\343\200\201\345\265\214\345\245\227.md" | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 "\351\273\204\345\256\207\347\205\214/7.10 Vue\350\267\257\347\224\261\345\274\202\346\255\245\345\212\240\350\275\275\343\200\201\345\265\214\345\245\227.md" diff --git "a/\351\273\204\345\256\207\347\205\214/7.10 Vue\350\267\257\347\224\261\345\274\202\346\255\245\345\212\240\350\275\275\343\200\201\345\265\214\345\245\227.md" "b/\351\273\204\345\256\207\347\205\214/7.10 Vue\350\267\257\347\224\261\345\274\202\346\255\245\345\212\240\350\275\275\343\200\201\345\265\214\345\245\227.md" new file mode 100644 index 0000000..a11133e --- /dev/null +++ "b/\351\273\204\345\256\207\347\205\214/7.10 Vue\350\267\257\347\224\261\345\274\202\346\255\245\345\212\240\350\275\275\343\200\201\345\265\214\345\245\227.md" @@ -0,0 +1,138 @@ +# Vue路由异步加载、嵌套 + +## 路由封装 + +安装路由依赖 + +```shell +yarn add vue-router +``` + +router 下 index.js 配置 + +```js +import Vue from 'vue' +import VueRouter from 'vue-router'; +import routes from './routes' + +Vue.use(VueRouter); + +let router = new VueRouter({ + mode: 'history', + routes +}) + +export default router +``` + +router 下 routes.js 配置 + +```js +import Layout from '../components/Layout' + +let routes = [ + { + path: '/', + component: Layout, + children:[ + { + path:'home', + component:()=>import('../components/Home') + }, + { + path:'show', + component:()=>import('../components/Show') + } + ] + } +] + +export default routes +``` + +## 完整引入 elemnt-ui + +安装 Elemen-ui + +```shell +yarn add element-ui +``` + +main.js 配置 + +```js +import Vue from 'vue' +import App from './App.vue' +// 引入 Element-ui +import ElementUI from 'element-ui'; +import 'element-ui/lib/theme-chalk/index.css'; + +import router from './router' + +Vue.config.productionTip = false + +// 使用ElementUI +Vue.use(ElementUI); + +new Vue({ + router, + render: h => h(App), +}).$mount('#app') +``` + +## Element-UI 下 Vue 路由嵌套 + +```html + +``` \ No newline at end of file -- Gitee