Live2D 看板娘 / Demo

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));
posted @ 2021-11-05 15:16  KysonDu  阅读(267)  评论(0编辑  收藏  举报