ASP.NET Core WebAPI学习-1

摘要:
WebAPI学习ASP.NETCoreWebAPI学习-1ASP.NETCore WebAPI学习-2ASP.NETCoreWebAPI学-3ASP.NETCoreWebAPI学习-4ASP.NETcore WebAPI学-5ASP.NETCore WebAPI学习-6创建WebAPI项目以打开Visual Studio,首先选择ASP.NETCore 3.1。这里选择了API模板,不使用HTTPS和Docker。查看json配置文件appsettings.jsonappsettings.Development.json注意:您需要了解appsettings.json和appsettings.Dvelopment.jsn之间的关系。请参阅在ASP中使用多个环境。NET核心https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/environments?Configure方法用于指定ASP。NET核心Web程序响应每个HTTP请求。通常,授权配置是在ConfigureServices方法中完成的,但我现在没有配置授权,而是配置了应用程序。UseAuthorization()仍然允许匿名访问API。修改项目启动配置。我喜欢使用控制台启动Web程序,这样我就可以直观地看到Log信息。

Web API学习

  1. ASP.NET Core WebAPI学习-1
  2. ASP.NET Core WebAPI学习-2
  3. ASP.NET Core WebAPI学习-3
  4. ASP.NET Core WebAPI学习-4
  5. ASP.NET Core WebAPI学习-5
  6. ASP.NET Core WebAPI学习-6

创建Web API项目

打开Visual Studio,首先要选择ASP.NET Core 3.1。
这里选择了API这个模板 ,取消使用HTTPS和Docker。

查看json配置文件

  1. appsettings.json
  2. appsettings.Development.json
    注意:您需要知道appsettings.json 和 appsettings.Development.json之间的关系

参考
在 ASP.NET Core 中使用多个环境
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/environments?WT.mc_id=DT-MVP-5003302&view=aspnetcore-3.1

删掉默认创建的示例文件:WeatherForecastController和WeatherForecast

Program.cs

Program类下的Main方法就是整个程序的入口,Main方法负责配置和运行整个Web程序。
由于这是一个Web项目,所以我们还需要一个宿主(Host),这个宿主就是由下面的CreateHostBuilder方法来负责创建的。该方法首先会创建出一个实现了IHostBuilder接口的类(HostBuilder)的实例,然后调用它的Build方法来创建宿主(类型为Host,实现了IHost接口),最后调用宿主上面的Run方法来运行程序。
我们暂时不修改这里面的代码,所以一切都会按照项目模板默认的配置进行,注意到下面的方法里我们使用到了Startup这个类:

Startup.cs

我们看到IConfiguration被注入了,这样就允许我们使用配置信息了,例如appsettings.json里面的配置信息。

ConfigureServices方法

这个方法负责向服务容器里面注册服务,已注册的服务可以通过依赖注入的方式在整个应用程序的其它地方进行使用。这里的服务是一个比较广义的概念,它就是一个在整个程序中做一些通用性操作的组件。

Configure方法

这个方法使用到了在ConfigureServices方法里面注册和配置的服务,所以这个方法是在ConfigureServices方法之后被调用的。
Configure方法是用来指定ASP.NET Core Web程序是如何响应每一个HTTP请求的。换句话说,也就是我们在这里配置请求的管道,配置的方法就是在这里添加很多中间件(Configure方法里面每一个app.UseXxx就是添加一个中间件,可以查看中间件的官方文档来了解更多)。
在开发环境的时候,如果有异常发生,那么会展示一个异常页面

 if (env.IsDevelopment())
 {
     app.UseDeveloperExceptionPage();
 }

app.UseAuthorization(),它会为整个Web程序添加授权的能力。当你需要考虑API安全性的时候,这点就很重要了。通常授权配置是在ConfigureServices方法里完成的,而我现在没有对授权进行配置,但是app.UseAuthorization()仍然会允许API可以被匿名的访问。

修改项目启动配置(不使用IIS启动WebAPI,使用SelfHost启动)

我喜欢使用控制台启动Web程序,这样可以很直观的看到Log信息。为达到这个目的,可以修改launchSettings.json文件:(把使用IIS启动项去掉) ,然后右键项目属性,在调试里面把启动项改为项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0VZaR0sd-1580486627721)(D: otewebapipic1.png)]

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "Routine.Api": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/companies",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    }
  }
}

添加SQLite数据库

想要做RESTful API的话,我们还需要数据,这里我准备采用SQLite来作为数据存储,使用Entity Framework Core 作为 ORM来与数据库进行交互。

  1. 安装EntityFramework Sqlite和Microsoft.EntityFrameworkCore.Tools包
  2. 创建Entity: Company Employee
using System;
using System.Collections.Generic;

namespace Routine.Api.Entity
{
    public class Company
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Introduction { get; set; }
        public ICollection<Employee> Employees { get; set; }
    }
}

using System;

namespace Routine.Api.Entity
{
    public class Employee
    {
        public Guid Id { get; set; }
        public string EmployeeNo { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Gender Gender { get; set; }
        public DateTimeOffset DateOfBirth { get; set; }
        public Guid CompanyId { get; set; }
        public Company Company { get; set; }
    }
    public enum Gender
    {
        男 = 1,
        女 = 2
    }
}
  1. 创建DbContext
using Microsoft.EntityFrameworkCore;
using Routine.Api.Entity;
using System;

namespace Routine.Api.Data
{
    public class RoutineDbContext : DbContext
    {
        public RoutineDbContext(DbContextOptions<RoutineDbContext> options) : base(options)
        {

        }
        public DbSet<Company> Companies { get; set; }
        public DbSet<Employee> Employees { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Company>()
                .Property(x => x.Name).IsRequired().HasMaxLength(100);
            modelBuilder.Entity<Company>()
                .Property(x => x.Introduction).HasMaxLength(500);

            modelBuilder.Entity<Employee>()
                .Property(x => x.EmployeeNo).IsRequired().HasMaxLength(10);
            modelBuilder.Entity<Employee>()
                .Property(x => x.FirstName).IsRequired().HasMaxLength(50);
            modelBuilder.Entity<Employee>()
                .Property(x => x.LastName).IsRequired().HasMaxLength(50);

            //配置公司员工一对多关系
            //配置级联删除,当公司有员工时,不允许删除
            modelBuilder.Entity<Employee>()
                .HasOne(x => x.Company)
                .WithMany(x => x.Employees)
                .HasForeignKey(x => x.CompanyId)
                .OnDelete(DeleteBehavior.Cascade);

            //添加种子数据
            //种子数据
            modelBuilder.Entity<Company>().HasData(
                new Company
                {
                    Id = Guid.Parse("bbdee09c-089b-4d30-bece-44df5923716c"),
                    Name = "Microsoft",
                    Introduction = "Great Company"
                },
                new Company
                {
                    Id = Guid.Parse("6fb600c1-9011-4fd7-9234-881379716440"),
                    Name = "Google",
                    Introduction = "Don't be evil"
                },
                new Company
                {
                    Id = Guid.Parse("5efc910b-2f45-43df-afee-620d40542853"),
                    Name = "Alipapa",
                    Introduction = "Fubao Company"
                }
            );
            modelBuilder.Entity<Employee>().HasData(
                new Employee
                {
                    Id = Guid.Parse("ca268a19-0f39-4d8b-b8d6-5bace54f8027"),
                    CompanyId = Guid.Parse("bbdee09c-089b-4d30-bece-44df5923716c"),
                    DateOfBirth = new DateTime(1955, 10, 28),
                    EmployeeNo = "M001",
                    FirstName = "William",
                    LastName = "Gates",
                    Gender = Gender.男
                },
                new Employee
                {
                    Id = Guid.Parse("265348d2-1276-4ada-ae33-4c1b8348edce"),
                    CompanyId = Guid.Parse("bbdee09c-089b-4d30-bece-44df5923716c"),
                    DateOfBirth = new DateTime(1998, 1, 14),
                    EmployeeNo = "M024",
                    FirstName = "Kent",
                    LastName = "Back",
                    Gender = Gender.男
                },
                new Employee
                {
                    Id = Guid.Parse("47b70abc-98b8-4fdc-b9fa-5dd6716f6e6b"),
                    CompanyId = Guid.Parse("6fb600c1-9011-4fd7-9234-881379716440"),
                    DateOfBirth = new DateTime(1986, 11, 4),
                    EmployeeNo = "G003",
                    FirstName = "Mary",
                    LastName = "King",
                    Gender = Gender.女
                },
                new Employee
                {
                    Id = Guid.Parse("059e2fcb-e5a4-4188-9b46-06184bcb111b"),
                    CompanyId = Guid.Parse("6fb600c1-9011-4fd7-9234-881379716440"),
                    DateOfBirth = new DateTime(1977, 4, 6),
                    EmployeeNo = "G007",
                    FirstName = "Kevin",
                    LastName = "Richardson",
                    Gender = Gender.男
                },
                new Employee
                {
                    Id = Guid.Parse("a868ff18-3398-4598-b420-4878974a517a"),
                    CompanyId = Guid.Parse("5efc910b-2f45-43df-afee-620d40542853"),
                    DateOfBirth = new DateTime(1964, 9, 10),
                    EmployeeNo = "A001",
                    FirstName = "Jack",
                    LastName = "Ma",
                    Gender = Gender.男
                },
                new Employee
                {
                    Id = Guid.Parse("2c3bb40c-5907-4eb7-bb2c-7d62edb430c9"),
                    CompanyId = Guid.Parse("5efc910b-2f45-43df-afee-620d40542853"),
                    DateOfBirth = new DateTime(1997, 2, 6),
                    EmployeeNo = "A201",
                    FirstName = "Lorraine",
                    LastName = "Shaw",
                    Gender = Gender.女
                }
            );

        }
    }
}

  1. 创建IRepository和Repository
    IRepository.cs:
using Routine.Api.Entity;
using Routine.Api.Helpers;
using Routine.Api.ResourceParameters;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Routine.Api.Services
{
    public interface ICompanyRepository
    {
        Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, string gender);
        Task<Employee> GetEmployeeAsync(Guid CompanyId, Guid employeeId);
        void AddEmployee(Guid companyId, Employee employee);
        void UpdateEmployee(Employee employee);
        void DeleteEmployee(Employee employee);


        Task<Company> GetCompanyAsync(Guid companyId);
        Task<PagedList<Company>> GetCompaniesAsync(CompanyDtoParameter parameter);
        Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds);
        void AddCompany(Company company);
        void DeleteCompany(Company company);
        void UpdateCompany(Company company);
        Task<bool> CompanyExistsAsync(Guid companyId);
        Task<bool> SaveAsync();
    }
}

Repository.cs

using Microsoft.EntityFrameworkCore;
using Routine.Api.Data;
using Routine.Api.Entity;
using Routine.Api.Helpers;
using Routine.Api.ResourceParameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Routine.Api.Services
{
    public class CompanyRepository : ICompanyRepository
    {
        private readonly RoutineDbContext context;

        public CompanyRepository(RoutineDbContext context)
        {
            this.context = context ?? throw new ArgumentNullException(nameof(context));
        }
        public void AddCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }
            company.Id = Guid.NewGuid();
            if (company.Employees != null)
            {
                foreach (var employee in company.Employees)
                {
                    employee.Id = Guid.NewGuid();
                }
            }

            context.Companies.Add(company);
        }

        public void AddEmployee(Guid companyId, Employee employee)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            if (employee == null)
            {
                throw new ArgumentNullException(nameof(employee));
            }
            employee.CompanyId = companyId;
            context.Employees.Add(employee);
        }

        public Task<bool> CompanyExistsAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            return context.Companies.AnyAsync(x => x.Id == companyId);
        }

        public void DeleteCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }
            context.Companies.Remove(company);
        }

        public void DeleteEmployee(Employee employee)
        {
            if (employee == null)
            {
                throw new ArgumentNullException(nameof(employee));
            }
            context.Employees.Remove(employee);
        }



        public async Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
        {
            if (companyIds == null)
            {
                throw new ArgumentNullException(nameof(companyIds));
            }
            return await context.Companies
                .Where(x => companyIds.Contains(x.Id))
                .OrderBy(a => a.Name)
                .ToListAsync();
        }

        public Task<Company> GetCompanyAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            return context.Companies
                .FirstOrDefaultAsync(a => a.Id == companyId);
        }

        public async Task<PagedList<Company>> GetCompaniesAsync(CompanyDtoParameter parameter)
        {
            if (parameter == null)
            {
                //return await context.Companies.ToListAsync();
                throw new ArgumentNullException(nameof(parameter));
            }

            //if (string.IsNullOrEmpty(parameter.CompanyName)&&
            //    string.IsNullOrEmpty(parameter.SearchTerm))
            //{
            //    return await context.Companies.ToListAsync();
            //}

            var queryExpression = context.Companies as IQueryable<Company>;
            if (!string.IsNullOrWhiteSpace(parameter.CompanyName))
            {
                queryExpression = queryExpression.Where(x => x.Name == parameter.CompanyName.Trim());
            }
            if (!string.IsNullOrWhiteSpace(parameter.SearchTerm))
            {
                queryExpression = queryExpression.Where(x => x.Name == parameter.SearchTerm.Trim() ||
                     x.Introduction.Contains(parameter.SearchTerm.Trim()));
            }
            //分页
            //queryExpression = queryExpression
            //    .Skip(parameter.PageSize * (parameter.PageNumber - 1))
            //    .Take(parameter.PageSize);
            //return await queryExpression.ToListAsync();
            return await PagedList<Company>.CreateAsync(queryExpression, parameter.PageNumber, parameter.PageSize);
        }

        public async Task<Employee> GetEmployeeAsync(Guid companyId, Guid employeeId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            if (employeeId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(employeeId));
            }
            return await context.Employees
                .Where(x => x.CompanyId == companyId && x.Id == employeeId)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, string gender)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            if (string.IsNullOrWhiteSpace(gender))
            {
                return await context.Employees
                    .Where(x => x.CompanyId == companyId)
                    .OrderBy(x => x.EmployeeNo)
                    .ToListAsync();
            }

            //判断Gender是否转换成功
            Gender gender1;
            var isGender = Enum.TryParse<Gender>(gender.Trim(), out gender1);
            if (isGender)
            {
                return await context.Employees
                .Where(x => x.CompanyId == companyId && x.Gender == gender1)
                .OrderBy(x => x.EmployeeNo)
                .ToListAsync();
            }
            else
            {
                throw new ArgumentNullException(nameof(gender));
            }

        }

        public async Task<bool> SaveAsync()
        {
            return await context.SaveChangesAsync() >= 0;
        }

        public void UpdateCompany(Company company)
        {
            context.Entry<Company>(company).State = EntityState.Modified;
        }

        public void UpdateEmployee(Employee employee)
        {

        }
    }
}

  1. 在Startup的ConfigureServices中配置DbContext和Repository依赖注入
services.AddScoped<ICompanyRepository, CompanyRepository>();
services.AddDbContext<RoutineDbContext>(optionsAction: option =>
{
     option.UseSqlite(connectionString: "Data Source=routine.db");
});
  1. 在Controller中使用Repository
//配置公司员工一对多关系
//配置级联删除,当公司有员工时,不允许删除
modelBuilder.Entity<Employee>()
    .HasOne(x => x.Company)
    .WithMany(x => x.Employees)
    .HasForeignKey(x => x.CompanyId)
    .OnDelete(DeleteBehavior.Restrict);

这里使用DeleteBehavior.Restrict,删除的时候,当公司下面有员工的时候会无法删除
7. 添加种子数据
为了演示方便,我让数据库在每次程序启动的时候都会被删掉并重新进行迁移,同时设置好种子数据。

using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Routine.Api.Data;
using System;

namespace Routine.Api
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            //为了获取dbcontext服务,因为这里还无法使用构造函数依赖注入服务
            using (var scope = host.Services.CreateScope())
            {
                try
                {
                    RoutineDbContext dbContext = scope.ServiceProvider.GetService<RoutineDbContext>();
                    dbContext.Database.EnsureDeleted();
                    dbContext.Database.Migrate();
                }
                catch (Exception ex)
                {
                    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, message: "Database Migration Error!");
                }
            }
            host.Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

  1. 添加数据迁移
Add-Migration Initial
  1. 运行程序,可以看到一下程序运行的过程中使用的SQL语句

免责声明:文章转载自《ASP.NET Core WebAPI学习-1》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇zzh的训练日志1十一、散列表(一)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

go微服务框架kratos学习笔记六(kratos 服务发现 discovery) 目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批量获取实例 nodes 批量获取节点 renew 心跳 cance...

OpenStack 中的neutron-server启动过程

neutron-server是neutron的核心组件之中的一个。负责直接接收外部请求,然后调用后端对应plugin进行处理。 其核心启动过程代码主要在neutron.server包中。 __init__.py文件里包含一个main()函数,是WSGIserver開始的模块,而且通过调用serve_wsgi来创建一个NeutronApiService的...

WebApi管理和性能测试工具WebApiBenchmarks

WebApiBenchmark 说到WebApi管理和测试工具其实已经非常多的了,Postman、Swagger等在管理和维护上都非常出色;在性能测试方面也有不少的工具如:wrk,bombardier,http_load和ab等等。不过这些工具都具有单一性,管理和维护好的在性能测试上比较低效,对于性能测试好的在管理和维护上不理想!以下主要介绍一款基于dotn...

guava API整理

1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection API Guava Basic Utilities IO API Cache API 2,为神马选择瓜娃? 瓜娃是java API蛋糕上的冰激凌(精华) 高效设计良好的API. 被google的开发者设计,实现和使用。...

Android Glide加载视频封面

/** *   context 上下文 *   uri 视频地址 *   imageView 设置image *   frameTimeMicros 获取某一时间帧 */ public void loadVideoScreenshot(final Context context, String ur...

普通Java类获取Spring的bean traceofsun的专栏 博客频道 CSDN.NET

普通Java类获取Spring的bean - traceofsun的专栏 - 博客频道 - CSDN.NET 普通Java类获取Spring的bean 分类:Extjs开发2010-08-13 09:47451人阅读评论(0)收藏举报 在SSH集成的前提下。某些情况我们需要在Action以外的类中来获得Spring所管理的Service对象...