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()
{
//ConfigId="db01" 多租户用到
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,
Id="Bearer"
}
},
new string[] {}
}
});
#endregion
});
#region 注入SqlSugarIOC
services.AddSqlSugar(new IocConfig()
{
//ConfigId="db01" 多租户用到
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));