ASP.NET Core 个人新闻项目

# 1.打开Microsoft Visual Studio 2019软件新建ASP.NET Core Web API(.NET 5.0)项目

# 2.数据库设计

新闻表

ID

新闻标题

新闻内容

创建时间

新闻类型ID

浏览量

点赞量

作者ID

```

新闻类型表

ID

类型名

```

作者表

ID

姓名

账号

密码 MD5

```

# 3.添加表的模型

操作:新建MyNews.Model类库

添加NuGet程序包:SqlSugarCore(官网:https://www.donet5.com/home/doc)

(1)新建BaseId类(公共类)

using SqlSugar;

namespace MyNews.Model

{

public class BaseId

{

//自增主键Id

[SugarColumn(IsIdentity = true, IsPrimaryKey = true)]

public int Id { get; set; }

}

}

(2)新建News类(新闻)

using System;

using SqlSugar;

namespace MyNews.Model

{

public class News : BaseId

{

//标题

[SugarColumn(ColumnDataType = "nvarchar(50)")]

public string Title { get; set; }

//内容

[SugarColumn(ColumnDataType = "text")]

public string Content { get; set; }

//创建时间

public DateTime CreateTime { get; set; }

//新闻类型Id

public int TypeId { get; set; }

//浏览量

public int BrowseCount { get; set; }

//点赞量

public int LikeCount { get; set; }

//作者Id

public int WriterId { get; set; }

#region ORM不处理该列(不映射到数据库)

[SugarColumn(IsIgnore = true)]

public NewsType NewsType { get; set; }

[SugarColumn(IsIgnore = true)]

public Writer Writer { get; set; }

#endregion

}

}

(3)新建NewsType类(新闻类型)

using SqlSugar;

namespace MyNews.Model

{

public class NewsType : BaseId

{

//新闻类型名

[SugarColumn(ColumnDataType ="nvarchar(20)")]

public string Name { get; set; }

}

}

(5)新建Writer类(作者)

using SqlSugar;

namespace MyNews.Model

{

public class Writer : BaseId

{

//作者姓名

[SugarColumn(ColumnDataType ="nvarchar(20)")]

public string Name { get; set; }

//账号

[SugarColumn(ColumnDataType ="nvarchar(20)")]

public string UserName { get; set; }

//密码

[SugarColumn(ColumnDataType ="nvarchar(100)")]

public string UserPwd { get; set; }

}

}

```

# 3.架构设计

仓储层(Repository):用于数据的增删改查

服务层(Service):调用仓储层

(1)新建仓储层

操作:新建Repository文件夹->新建MyNews.IRepository类库(接口)和MyNews.Repository类库(实现接口)

①在MyNews.IRepository类库中新建IBaseRepository类(主要是增删改查方法)

添加NuGet程序包:SqlSugarCore(官网:https://www.donet5.com/home/doc)

using SqlSugar;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.IRepository

{

public interface IBaseRepository<T> where T : class, new()

{

/// <summary>

/// 增加

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

Task<bool> CreateAsync(T entity);

/// <summary>

/// 删除

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

Task<bool> DeleteAsync(int id);

/// <summary>

/// 修改

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

Task<bool> EditAsync(T entity);

/// <summary>

/// 查询单条数据

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

Task<T> FindAsync(int id);

/// <summary>

/// 查询单条数据(自定义)

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

Task<T> FindAsync(Expression<Func<T, bool>> func);

/// <summary>

/// 查询全部数据

/// </summary>

/// <returns></returns>

Task<List<T>> QueryAsync();

/// <summary>

/// 自定义条件查询

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(Expression<Func<T, bool>> func);

/// <summary>

/// 分页查询

/// </summary>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(int page, int size, RefAsync<int> total);

/// <summary>

/// 分页查询(自定义)

/// </summary>

/// <param name="func"></param>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(Expression<Func<T, bool>> func, int page, int size, RefAsync<int> total);

}

}

②在MyNews.Repository类库中新建BaseRepository类

添加NuGet程序包:SqlSugarCore(官网:https://www.donet5.com/home/doc)

添加NuGet程序包:SqlSugar.IOC(参考:https://www.donet5.com/Doc/10)

前提:在MyNews.WebApi项目(也要引用SqlSugar程序包)Startup类中注入SqlSugarIOC

services.AddSqlSugar(new IocConfig()

{

//Config 多租户用到

ConnectionString =this.Configuration["SqlConn"],

DbType = IocDbType.SqlServer,

IsAutoCloseConnection = true//自动释放

});

这里把数据库连接字符串放在了appsetting.json文件里: "SqlConn": "Server=(localdb)\\MSSQLLocalDB;Database=MyNewsDB;Trusted_Connection=True;"

using MyNews.IRepository;

using MyNews.Model;

using SqlSugar;

using SqlSugar.IOC;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.Repository

{

public class BaseRepository<T> : SimpleClient<T>, IBaseRepository<T> where T : class, new()

{

public BaseRepository(ISqlSugarClient context = null) : base(context)//注意这里要有默认值等于null

{

base.Context = DbScoped.SugarScope;

#region 创建数据库和表

//DbScoped.Sugar上下文共享 除了SugarIoc 你还可以用SqlSugarScope单例模式实现

//base.Context.DbMaintenance.CreateDatabase();//创建数据库

//base.Context.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(News), typeof(NewsType), typeof(Writer));//这样一个表就能成功创建了

#endregion

}

/// <summary>

/// 增加

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

public async Task<bool> CreateAsync(T entity)

{

return await base.InsertAsync(entity);

}

/// <summary>

/// 删除

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

public async Task<bool> DeleteAsync(int id)

{

return await base.DeleteByIdAsync(id);

}

/// <summary>

/// 修改

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

public async Task<bool> EditAsync(T entity)

{

return await base.UpdateAsync(entity);

}

/// <summary>

/// 查询单条数据

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

public virtual async Task<T> FindAsync(int id)

{

return await base.GetByIdAsync(id);

}

/// <summary>

/// 查询单条数据(自定义)

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

public virtual async Task<T> FindAsync(Expression<Func<T, bool>> func)

{

return await base.GetSingleAsync(func);

}

/// <summary>

/// 查询全部数据

/// </summary>

/// <returns></returns>

public virtual async Task<List<T>> QueryAsync()

{

return await base.GetListAsync();

}

/// <summary>

/// 自定义条件查询

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

public virtual async Task<List<T>> QueryAsync(Expression<Func<T, bool>> func)

{

return await base.GetListAsync(func);

}

/// <summary>

/// 分页

/// </summary>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

public virtual async Task<List<T>> QueryAsync(int page, int size, RefAsync<int> total)

{

return await base.Context.Queryable<T>().ToPageListAsync(page, size, total);

}

/// <summary>

/// 自定义条件分页查询

/// </summary>

/// <param name="func"></param>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

public virtual async Task<List<T>> QueryAsync(Expression<Func<T, bool>> func, int page, int size, RefAsync<int> total)

{

return await base.Context.Queryable<T>().Where(func).ToPageListAsync(page, size, total);

}

}

}

③在MyNews.IRepository类库中新建INewsRepository、INewsTypeRepository、IWriterRepository接口分别继承IBaseRepository接口

using MyNews.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.IRepository

{

public interface INewsRepository : IBaseRepository<News>

{

}

}

④在MyNews.Repository类库中新建NewsRepository、NewsTpyeRepository、WriterRepository类分别继承BaseRepository类,并实现对应接口

using MyNews.IRepository;

using MyNews.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.Repository

{

public class NewsRepository : BaseRepository<News>, INewsRepository

{

}

}

(2)新建服务层

操作:新建Service文件夹->新建MyNews.IService类库(接口)和MyNews.Service类库(实现接口)

①在MyNews.IService类库中新建IBaseService类(主要是增删改查方法)

添加NuGet程序包:SqlSugarCore(官网:https://www.donet5.com/home/doc)

using SqlSugar;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.IService

{

public interface IBaseService<T> where T : class, new()

{

/// <summary>

/// 增加

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

Task<bool> CreateAsync(T entity);

/// <summary>

/// 删除

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

Task<bool> DeleteAsync(int id);

/// <summary>

/// 修改

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

Task<bool> EditAsync(T entity);

/// <summary>

/// 查询单条数据

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

Task<T> FindAsync(int id);

/// <summary>

/// 查询单条数据(自定义)

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

Task<T> FindAsync(Expression<Func<T, bool>> func);

/// <summary>

/// 查询全部数据

/// </summary>

/// <returns></returns>

Task<List<T>> QueryAsync();

/// <summary>

/// 自定义条件查询

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(Expression<Func<T, bool>> func);

/// <summary>

/// 分页

/// </summary>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(int page, int size, RefAsync<int> total);

/// <summary>

/// 分页查询(自定义)

/// </summary>

/// <param name="func"></param>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

Task<List<T>> QueryAsync(Expression<Func<T, bool>> func, int page, int size, RefAsync<int> total);

}

}

②在MyNews.BaseService类库中新建BaseService类

添加IBaseRepository项目的引用

using MyNews.IRepository;

using MyNews.IService;

using SqlSugar;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.Service

{

public class BaseService<T> : IBaseService<T> where T : class, new()

{

protected IBaseRepository<T> baseRepository;

/// <summary>

/// 增加

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

public async Task<bool> CreateAsync(T entity)

{

return await baseRepository.CreateAsync(entity);

}

/// <summary>

/// 删除

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

public async Task<bool> DeleteAsync(int id)

{

return await baseRepository.DeleteAsync(id);

}

/// <summary>

/// 修改

/// </summary>

/// <param name="entity">传入的类</param>

/// <returns></returns>

public async Task<bool> EditAsync(T entity)

{

return await baseRepository.EditAsync(entity);

}

/// <summary>

/// 查询单条数据

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

public async Task<T> FindAsync(int id)

{

return await baseRepository.FindAsync(id);

}

/// <summary>

/// 查询单条数据(自定义)

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

public async Task<T> FindAsync(Expression<Func<T, bool>> func)

{

return await baseRepository.FindAsync(func);

}

/// <summary>

/// 查询全部数据

/// </summary>

/// <returns></returns>

public async Task<List<T>> QueryAsync()

{

return await baseRepository.QueryAsync();

}

/// <summary>

/// 查询全部数据(自定义)

/// </summary>

/// <param name="func"></param>

/// <returns></returns>

public async Task<List<T>> QueryAsync(Expression<Func<T, bool>> func)

{

return await baseRepository.QueryAsync(func);

}

/// <summary>

/// 分页查询(自定义)

/// </summary>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

public async Task<List<T>> QueryAsync(int page, int size, RefAsync<int> total)

{

return await baseRepository.QueryAsync(page, size, total);

}

/// <summary>

/// 分页查询(自定义)

/// </summary>

/// <param name="func"></param>

/// <param name="page"></param>

/// <param name="size"></param>

/// <param name="total"></param>

/// <returns></returns>

public async Task<List<T>> QueryAsync(Expression<Func<T, bool>> func, int page, int size, RefAsync<int> total)

{

return await baseRepository.QueryAsync(func,page, size, total);

}

}

}

③在MyNews.IService类库中新建INewsService、INewsTypeService、IWriterService接口分别继承IBaseService接口

using MyNews.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.IService

{

public interface INewsService : IBaseService<News>

{

}

}

④IOC依赖注入

在MyNews.WebApi项目(项目引用:MyNews.IRepository、MyNews.Repository、MyNews.IService、MyNews.Service)Startup类中注入IOC

新建IOCExtend类

public static class IOCExtend

{

public static IServiceCollection AddCustomIOC(this IServiceCollection services)

{

services.AddScoped<INewsRepository, NewsRepository>();

services.AddScoped<INewsTypeRepository, NewsTypeRepository>();

services.AddScoped<IWriterRepository, WriterRepository>();

services.AddScoped<INewsService, NewsService>();

services.AddScoped<INewsTypeService, NewsTypeService>();

services.AddScoped<IWriterService, WriterService>();

return services;

}

}

注入

#region IOC依赖注入

services.AddCustomIOC();

#endregion

④在MyNews.Service类库中新建NewsService、NewsTpyeService、WriterService类分别继承BaseService类,并实现对应接口

using MyNews.IRepository;

using MyNews.IService;

using MyNews.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.Service

{

public class NewsService : BaseService<News>, INewsService

{

private INewsRepository newsRepository;

public NewsService(INewsRepository newsRepository)

{

base.baseRepository = newsRepository;

this.newsRepository = newsRepository;

}

}

}

# 5.新建数据库和表

在MyNews.WebApi项目Controllers文件夹新建NewsControllers控制器实现News的查询,然后运行程序打开swagger进入News方法执行就可以完成新建数据库和表(方法写在仓储层)

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using MyNews.IService;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.Controllers

{

[Route("api/[controller]")]

[ApiController]

public class NewsController : ControllerBase

{

private readonly INewsService newsService;

public NewsController(INewsService newsService)

{

this.newsService = newsService;

}

[HttpGet("News")]

public async Task<ActionResult> GetBlogNews()

{

var data = await newsService.QueryAsync();

return Ok(data);

}

}

}

# 6.封装API返回结果

在MyNews.WebApi项目新建Utility文件夹->ApiResult文件夹->ApiResult类和ApiResultHelper类

ApiResult.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.WebApi.Utility.ApiResult

{

public class ApiResult

{

//状态字码

public int Code { get; set; }

//数据

public dynamic Data { get; set; }

//返回成功/错误信息

public string Msg { get; set; }

//数据总条数

public int Total { get; set; }

}

}

ApiResultHelper

using SqlSugar;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.WebApi.Utility.ApiResult

{

public static class ApiResultHelper

{

/// <summary>

/// 成功后返回的数据

/// </summary>

/// <param name="data">数据</param>

/// <returns></returns>

public static ApiResult Success(dynamic data)

{

return new ApiResult

{

Code = 200,

Data = data,

Msg = "操作成功",

Total = 0

};

}

/// <summary>

/// 成功后返回的数据(分页)

/// </summary>

/// <param name="data">数据</param>

/// <returns></returns>

public static ApiResult Success(dynamic data, RefAsync<int> total)

{

return new ApiResult

{

Code = 200,

Data = data,

Msg = "操作成功",

Total = total

};

}

/// <summary>

/// 失败后返回的数据

/// </summary>

/// <param name="msg"></param>

/// <returns></returns>

public static ApiResult Error(string msg)

{

return new ApiResult

{

Code = 500,

Data = null,

Msg = msg,

Total = 0

};

}

}

}

# 7.新闻、新闻类型、用户增删改查

(1)新闻

using AutoMapper;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using MyNews.IService;

using MyNews.Model;

using MyNews.Model.DTO;

using MyNews.WebApi.Utility.ApiResult;

using SqlSugar;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.WebApi.Controllers

{

[Route("api/[controller]")]

[ApiController]

[Authorize]

public class NewsController : ControllerBase

{

private readonly INewsService newsService;

public NewsController(INewsService newsService)

{

this.newsService = newsService;

}

/// <summary>

/// 添加文章

/// </summary>

/// <param name="title"></param>

/// <param name="content"></param>

/// <returns></returns>

[HttpPost("Create")]

public async Task<ActionResult<ApiResult>> Create(string title, string content, int typeid)

{

News news = new News

{

BrowseCount = 0,

Content = content,

LikeCount = 0,

CreateTime = DateTime.Now,

Title = title,

TypeId = typeid,

WriterId = Convert.ToInt32(this.User.FindFirst("Id").Value)

};

bool b = await newsService.CreateAsync(news);

if (!b)

{

return ApiResultHelper.Error("添加失败,服务器发生错误");

}

return ApiResultHelper.Success(news);

}

/// <summary>

/// 删除新闻

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

[HttpDelete("Delete")]

public async Task<ActionResult<ApiResult>> Delete(int id)

{

bool b = await newsService.DeleteAsync(id);

if (!b)

{

return ApiResultHelper.Error("删除失败");

}

return ApiResultHelper.Success(b);

}

/// <summary>

/// 修改新闻

/// </summary>

/// <param name="id"></param>

/// <param name="title"></param>

/// <param name="content"></param>

/// <param name="typeid"></param>

/// <returns></returns>

[HttpPut("Edit")]

public async Task<ActionResult<ApiResult>> Edit(int id, string title, string content, int typeid)

{

var blogNews = await newsService.FindAsync(id);

if (blogNews == null)

{

return ApiResultHelper.Error("没有找到该新闻");

}

blogNews.Title = title;

blogNews.Content = content;

blogNews.TypeId = typeid;

blogNews.WriterId = Convert.ToInt32(this.User.FindFirst("Id").Value);

bool b = await newsService.EditAsync(blogNews);

if (!b)

{

return ApiResultHelper.Error("修改失败");

}

return ApiResultHelper.Success(blogNews);

}

///// <summary>

///// 查询新闻

///// </summary>

///// <returns></returns>

//[HttpGet("News")]

//public async Task<ActionResult<ApiResult>> GetBlogNews()

//{

// var data = await newsService.QueryAsync();

// if (data.Count == 0)

// {

// return ApiResultHelper.Error("没有更多的新闻");

// }

// return ApiResultHelper.Success(data);

//}

/// <summary>

/// 导航查询新闻(查询当前登录用户所属的新闻 )

/// </summary>

/// <returns></returns>

[HttpGet("News")]

public async Task<ActionResult<ApiResult>> GetBlogNews()

{

int id = Convert.ToInt32(this.User.FindFirst("Id").Value);

var data = await newsService.QueryAsync(c => c.WriterId == id);

if (data.Count == 0)

{

return ApiResultHelper.Error("没有更多的新闻");

}

return ApiResultHelper.Success(data);

}

/// <summary>

/// 分页查询

/// </summary>

/// <param name="iMapper"></param>

/// <param name="page"></param>

/// <param name="size"></param>

/// <returns></returns>

[HttpGet("NewsPage")]

public async Task<ApiResult> GetBlogNewsPage([FromServices] IMapper iMapper, int page, int size)

{

RefAsync<int> total = 0;

var news = await newsService.QueryAsync(page, size, total);

try

{

var newsDTO = iMapper.Map<List<NewsDTO>>(news);

return ApiResultHelper.Success(newsDTO, total);

}

catch (Exception)

{

return ApiResultHelper.Error("AutoMapper映射错误");

}

}

}

}

(2)新闻类型

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using MyNews.IService;

using MyNews.Model;

using MyNews.WebApi.Utility.ApiResult;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.WebApi.Controllers

{

[Route("api/[controller]")]

[ApiController]

[Authorize]

public class NewsTpyeController : ControllerBase

{

private readonly INewsTypeService newsTypeService;

public NewsTpyeController(INewsTypeService newsTypeService)

{

this.newsTypeService = newsTypeService;

}

/// <summary>

/// 添加新闻类型

/// </summary>

/// <param name="name"></param>

/// <returns></returns>

[HttpPost("Create")]

public async Task<ApiResult> Create(string name)

{

#region 数据验证

if (String.IsNullOrWhiteSpace(name))

{

return ApiResultHelper.Error("新闻类型名不能为空");

}

#endregion

NewsType type = new NewsType

{

Name = name

};

bool b = await newsTypeService.CreateAsync(type);

if (!b)

{

return ApiResultHelper.Error("添加失败");

}

return ApiResultHelper.Success(type);

}

/// <summary>

/// 删除新闻类型

/// </summary>

/// <param name="id"></param>

/// <returns></returns>

[HttpDelete("Delete")]

public async Task<ApiResult> Delete(int id)

{

bool b = await newsTypeService.DeleteAsync(id);

if (!b)

{

return ApiResultHelper.Error("删除失败");

}

return ApiResultHelper.Success(b);

}

/// <summary>

/// 修改新闻类型

/// </summary>

/// <param name="id"></param>

/// <param name="title"></param>

/// <param name="content"></param>

/// <param name="typeid"></param>

/// <returns></returns>

[HttpPut("Edit")]

public async Task<ApiResult> Edit(int id, string name)

{

var type = await newsTypeService.FindAsync(id);

if (type == null)

{

return ApiResultHelper.Error("没有找到该新闻类型");

}

type.Name = name;

bool b = await newsTypeService.EditAsync(type);

if (!b)

{

return ApiResultHelper.Error("修改失败");

};

return ApiResultHelper.Success(type);

}

/// <summary>

/// 查询新闻类型

/// </summary>

/// <returns></returns>

[HttpGet("NewsType")]

public async Task<ApiResult> Types()

{

var data = await newsTypeService.QueryAsync();

if (data.Count == 0)

{

return ApiResultHelper.Error("没有更多的类型");

}

return ApiResultHelper.Success(data);

}

}

}

(3)作者

using AutoMapper;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using MyNews.IService;

using MyNews.Model;

using MyNews.Model.DTO;

using MyNews.WebApi.Utility._MD5;

using MyNews.WebApi.Utility.ApiResult;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace MyNews.WebApi.Controllers

{

[Route("api/[controller]")]

[ApiController]

[Authorize]

public class WriterController : ControllerBase

{

private readonly IWriterService writerService;

public WriterController(IWriterService writerService)

{

this.writerService = writerService;

}

/// <summary>

/// 添加用户

/// </summary>

/// <param name="name"></param>

/// <param name="username"></param>

/// <param name="userpwd"></param>

/// <returns></returns>

[HttpPost("Create")]

public async Task<ApiResult> Create(string name, string username, string userpwd)

{

//数据校验

Writer writer = new Writer

{

Name = name,

//加密密码

UserPwd = MD5Helper.MD5Encrypt32(userpwd),

UserName = username

};

//判断数据库中是否已经存在账号跟要添加的账号相同的数据

var oldWriter = await writerService.FindAsync(c => c.UserName == username);

if (oldWriter != null)

{

return ApiResultHelper.Error("账号已经存在");

}

bool b = await writerService.CreateAsync(writer);

if (!b)

{

return ApiResultHelper.Error("添加失败");

}

return ApiResultHelper.Success(writer);

}

/// <summary>

/// 修改用户

/// </summary>

/// <param name="name"></param>

/// <returns></returns>

[HttpPut("Edit")]

public async Task<ApiResult> Edit(string name)

{

int id = Convert.ToInt32(this.User.FindFirst("Id").Value);

var writer = await writerService.FindAsync(id);

writer.Name = name;

bool b = await writerService.EditAsync(writer);

if (!b) return ApiResultHelper.Error("修改失败");

return ApiResultHelper.Success("修改成功");

}

/// <summary>

/// 查询用户

/// </summary>

/// <param name="iMapper"></param>

/// <param name="id"></param>

/// <returns></returns>

[AllowAnonymous]//匿名访问

[HttpGet("FindWriter")]

public async Task<ApiResult> FindWriter([FromServices] IMapper iMapper, int id)

{

var writer = await writerService.FindAsync(id);

var writerDTO = iMapper.Map<WriterDTO>(writer);

return ApiResultHelper.Success(writerDTO);

}

}

}

# 8.JWT的使用

(1)JWT授权

①添加一个webapi项目

新建JWT文件夹->MyNews.JWT项目

添加NuGet程序包:SqlSugarCore(官网:https://www.donet5.com/home/doc)

②安装Nuget程序包 System.IdentityModel.Tokens.Jwt

③复制WebAapi项目中的Startup类中的代码到MyNews.JWT项目中Startup类中、UTIlity文件夹

④新建控制器AuthoizeController

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Microsoft.IdentityModel.Tokens;

using MyNews.IService;

using MyNews.JWT.Utility._MD5;

using MyNews.JWT.Utility.ApiResult;

using System;

using System.Collections.Generic;

using System.IdentityModel.Tokens.Jwt;

using System.Linq;

using System.Security.Claims;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.JWT.Controllers

{

[Route("api/[controller]")]

[ApiController]

public class AuthoizeController : ControllerBase

{

private readonly IWriterService writerService;

public AuthoizeController(IWriterService writerService)

{

this.writerService = writerService;

}

/// <summary>

/// JWT授权

/// </summary>

/// <param name="username"></param>

/// <param name="userpwd"></param>

/// <returns></returns>

[HttpPost("Login")]

public async Task<ApiResult> Login(string username, string userpwd)

{

//加密后的密码 123456 =>E1ADC3949BA59ABBE56E057F2F883E

string pwd = MD5Helper.MD5Encrypt32(userpwd);

//数据校验

var writer = await writerService.FindAsync(c => c.UserName == username && c.UserPwd == pwd);

if (writer != null)

{

//登陆成功

var claims = new Claim[]

{

new Claim(ClaimTypes.Name, writer.Name),

new Claim("Id", writer.Id.ToString()),

new Claim("UserName", writer.UserName)

//不能放敏感信息

};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SDMC-CJAS1-SAD-DFSFA-SADHJVF-VF"));

//issuer代表颁发Token的Web应用程序,audience是Token的受理者

var token = new JwtSecurityToken(

issuer: "http://localhost:6060",//JWT地址

audience: "http://localhost:5000",//webApi地址

claims: claims,

notBefore: DateTime.Now,

expires: DateTime.Now.AddHours(1),

signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)

);

var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

return ApiResultHelper.Success(jwtToken);

}

else

{

return ApiResultHelper.Error("账号或密码错误");

}

}

}

}

(2)JWT鉴权

在MyNews.WebApi项目Startup类中添加app.UseAuthentication();//鉴权

using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.AspNetCore.HttpsPolicy;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

using Microsoft.Extensions.Logging;

using Microsoft.IdentityModel.Tokens;

using Microsoft.OpenApi.Models;

using MyNews.IRepository;

using MyNews.IService;

using MyNews.Repository;

using MyNews.Service;

using MyNews.WebApi.Utility._AutoMapper;

using SqlSugar.IOC;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyNews.WebApi

{

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();

services.AddSwaggerGen(c =>

{

c.SwaggerDoc("v1", new OpenApiInfo { Title = "MyNews", Version = "v1" });

#region Swagger使用鉴权组件

c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme

{

In = ParameterLocation.Header,

Type = SecuritySchemeType.ApiKey,

Description = "直接在下框中输入Bearer {token}(注意两者之间是一个空格)",

Name = "Authorization",

BearerFormat = "JWT",

Scheme = "Bearer"

});

c.AddSecurityRequirement(new OpenApiSecurityRequirement

{

{

new OpenApiSecurityScheme

{

Reference=new OpenApiReference

{

Type=ReferenceType.SecurityScheme,

}

},

new string[] {}

}

});

#endregion

});

#region 注入SqlSugarIOC

services.AddSqlSugar(new IocConfig()

{

//Config 多租户用到

ConnectionString = this.Configuration["SqlConn"],

DbType = IocDbType.SqlServer,

IsAutoCloseConnection = true//自动释放

});

#endregion

#region IOC依赖注入

services.AddCustomIOC();

#endregion

#region JWT鉴权

services.AddCustomJWT();

#endregion

#region 注入AutoMapper

services.AddAutoMapper(typeof(CustomAutoMapperProfile));

#endregion

}

// 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.UseSwagger();

app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyNews v1"));

}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();//鉴权

app.UseAuthorization();

app.UseEndpoints(endpoints =>

{

endpoints.MapControllers();

});

}

}

public static class IOCExtend

{

public static IServiceCollection AddCustomIOC(this IServiceCollection services)

{

services.AddScoped<INewsRepository, NewsRepository>();

services.AddScoped<INewsTypeRepository, NewsTypeRepository>();

services.AddScoped<IWriterRepository, WriterRepository>();

services.AddScoped<INewsService, NewsService>();

services.AddScoped<INewsTypeService, NewsTypeService>();

services.AddScoped<IWriterService, WriterService>();

return services;

}

public static IServiceCollection AddCustomJWT(this IServiceCollection services)

{

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

.AddJwtBearer(options =>

{

options.TokenValidationParameters = new TokenValidationParameters

{

ValidateIssuerSigningKey = true,

IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SDMC-CJAS1-SAD-DFSFA-SADHJVF-VF")),

ValidateIssuer = true,

ValidIssuer = "http://localhost:6060",

ValidateAudience = true,

ValidAudience = "http://localhost:5000",

ValidateLifetime = true,

ClockSkew = TimeSpan.FromMinutes(60)

};

});

return services;

}

}

}

# 9.AutoMapper(官网https://automapper.org/)

(1)安装Nuget AutoMapper.Extensions.Microsoft.DependencyInjection

定义一个类,继承Profile

public class CustomAutoMapperProfile:Profile

{

public CustomAutoMapperProfile()

{

base.CreateMap<Writer, WriterDTO>();

}

}

(2)在服务中注册

services.AddAutoMapper(typeof(CustomAutoMapperProfile));

构造函数注入

private readonly IMapper _mapper;

public StudentsController(IMapper mapper)

{

this._mapper = mapper;

}

(4)复杂映射

base.CreateMap<Admin, AdminDto>()

.ForMember(dest => dest.RoleMsg, sourse => sourse.MapFrom(src => src.RoleInfo.RoleMsg));