一、ABP学习文档


ABP的由来

从零开始创建一个企业应用程序是一件繁琐的事,因为需要重复做很多常见的基础工作。许多公司都在开发自己的应用程序框架来重用于不同的项目,然后在框架的基础上开发一些新的功能。但并不是每个公司都有这样的实力。ABP因此诞生,作者之所以把项目命名为“ASP.NET Boilerplate”,就是希望它能成为开发一般企业WEB应用的新起点,直接把ABP作为项目模板。

一、什么是ABP

ABP是为新的现代Web应用程序使用最佳实践和使用最流行工具的一个起点。可作为一般用途的应用程序的基础框架或项目模板。ABP 提供了一个应用程序开发模型用于最佳实践。它拥有基础类、接口和工具使我们容易建立起可维护的大规模的应用程序。

二、ABP具有什么的功能

  • 依赖注入:ABP使用并提供一个强大而且符合约定的DI框架。上述的应用服务,按照约定临时的(每个请求Request创建一个)注册到DI容器,它能简单地注入所有依赖项(如示例中的Irepository)。
  • 仓储:ABP能为每个实体创建一个默认的仓储(如示例中的Irepository)。默认仓储包含许多有用的方法,如示例中的FirstOrDefault方法。我们可以根据需要,很容易地扩展默认仓储。仓储抽象了DBMS和ORM以及简化了数据访问逻辑。
  • 授权:ABP可以检查许可。如果当前用户没有“updating
    task”权限或是未登录,ABP就会阻止他们访问UpdateTask方法。用陈述性的特性来简化授权,当然还有另外的授权方式。
  • 验证:ABP自动检查input是否为null。根据标准的数据注释特性和自定义验证规则,检查一个input的所有属性。如果请求没有通过验证,会抛出一个对应的验证异常。
  • 审计日志:根据约定和配置,每个请求的用户、浏览器、Ip地址、调用服务、方法、参数、调用时间、执行耗时和其它的一些信息会被自动地保存下来。
  • 工作单元:在ABP里,每个应用服务方法都默认地被认定为一个工作单元。在方法开始前,它自动创建一个连接并开启一个事务。如果方法成功完成,接着事务会被提交并释放连接。即使是使用不同的仓储或是方法,它们都可以是原子性(事务性)的,并且当事务提交时实体中所有的修改都自动地被保存。因此,如同示例所示,我们甚至不需要去调用_repository.Update(task)方法。
  • 异常处理:我们几乎不用在一个使用ABP的Web应用中写异常处理。所有的异常都自动地被默认处理。当一个异常发生,ABP自动记录它并返回一个对应的结果给客户端。例如,一个AJAX请求,它会返回一个Json对象给客户端,告知发生了一个错误。如示例所示,UserFriendlyException可以向客户端隐藏具体的异常,显示友好信息。它同样可以在客户端理解并处理客户端错误,并向用户显示对应的信息。
  • 日志:如你所见,我们可以用定义在基类中的Logger对象写日志。默认使用Log4Net,不过这是可修改和可配置的。
  • 本地化:请注意我们在抛出异常时,使用了L方法。因此,它可自动依据用户区域,使用相应的本地化信息。当然,我们需要在某处定义CouldNotFoundTheTaskMessage(更多信息参见“本地化”文档)。
  • 自动映射:最后一行代码,我们使用ABP的MapTo扩展方法来映射input属性到实体属性。它使用AutoMapper库来执行映射。因此,我们可以简单地基于命名约定,从一个对象映射到另一个。
  • 动态Web API 层:实际上TaskAppService是一个简单的类(甚至是不需要从ApplicationService继承)。我们通常包装一个Web API 控制器为Javascript客户端公开方法,ABP会在运行时自动地完成这件事。因此,我们可以直接在客户端使用应用服务。
  • 动态Javascript AJAX 代理:ABP创建Javascript代理方法,以便就本地调用一样,来调用应用服务。

三、如何搭建启动一个ABP项目

  1. 去官网下载一个ABP项目,并填写你的项目名。https://aspnetboilerplate.com/Templates
    在这里插入图片描述

  2. 解压zip文件,用visual studio打开解决方案。并修改Web.Host项目下的appsetting.json文件,配置数据库连接字符串。
    在这里插入图片描述

  3. 设置EntityFrameworkCore项目为启动项目,并打开程序包管理控制台
    在这里插入图片描述

输入命令:Add-Migration,会看到在这个项目下会生成好多个文件
在这里插入图片描述
在这里插入图片描述

再执行命令:Update-Database
在这里插入图片描述

命令执行完后会自动生成一个新的数据库。
在这里插入图片描述
把Web.Host设置为启动项目,并启动程序。
在这里插入图片描述

  1. 启动前端Vue项目,用visual studio code打开Vue项目
    在这里插入图片描述

打开一个新的TERMINAL
在这里插入图片描述
输入命令:npm install ,安装项目所依赖的包(第一次安装需要较长的时间,请耐心等候)。
在这里插入图片描述
所有依赖包都安装完成后,执行命令:npm run serve,启动项目(账号:admin,密码:123qwe)。
在这里插入图片描述
在这里插入图片描述

四、如何添加一个简单的功能

  1. 在Core项目下定义一个APJUser类:
public class APJUser : Entity<int>
    {
        [Column("Id")]
        public override int Id { get; set; }

        public string Name { get; set; }

        public string Gender { get; set; }

        public string Email { get; set; }
    }
  1. 在EntityFrameworkCore项目下,找到DbContext,并添加以下代码:
 public DbSet<APJUser> APJUsers { get; set; }
  1. 执行命令:Add-Migration(注意:要将EntityFrameworkCore设置为启动项目)
    在这里插入图片描述
    再执行命令:Update-Database
    在这里插入图片描述
    会看到在数据库中会多了APJUser这么一张表:
    在这里插入图片描述

我们往表中插入几条数据,方便我们测试:

INSERT INTO [dbo].[APJUsers]
([Name],[Gender],[Email])
VALUES
('Tim','男','182317676@test.com'),
('Jimmy','男','154317676@test.com'),
('Lily','女','121317676@test.com'),
('Jenny','女','165317676@test.com')
  1. 在项目Application中,创建以下几个类:
    在这里插入图片描述
    [AutoMapFrom(typeof(APJUser))]
    public class APJUserDto: EntityDto
    {
        public string Name { get; set; }

        public string Gender { get; set; }

        public string Email { get; set; }

    }

    [AutoMapTo(typeof(APJUser))]
    public class CreateAPJUserDto
    {
        public string Name { get; set; }

        public string Gender { get; set; }

        public string Email { get; set; }
    }

    public class PagedAPJUserResultRequestDto : PagedResultRequestDto
    {
        public string Keyword { get; set; }
        public bool? IsActive { get; set; }
    }

    public interface IAPJUserAppService : IAsyncCrudAppService<APJUserDto, int, PagedAPJUserResultRequestDto, CreateAPJUserDto, APJUserDto>
    {
    }

    public class APJUserAppService : AsyncCrudAppService<APJUser, APJUserDto, int, PagedAPJUserResultRequestDto, CreateAPJUserDto, APJUserDto>, IAPJUserAppService
    {
        private IRepository<APJUser, int> _repository;

        public APJUserAppService(IRepository<APJUser, int> repository) : base(repository)
        {
            _repository = repository;
        }
    }

然后启动项目,看一下预期效果:
在这里插入图片描述
ABP会帮助我们自动生成相应的API,实现CRUD的功能,下面我们来调用一下,发现有几个问题。
问题一:GetAll()方法中,KeyWord参数设置无效。

修改方法,在APJUserAppService重写一下CreateFilteredQuery()的方法
protected override IQueryable CreateFilteredQuery(PagedAPJUserResultRequestDto input)
{
return _repository.GetAll().WhereIf(!string.IsNullOrWhiteSpace(input.Keyword), t => t.Name.Contains(input.Keyword));
}

问题二:Update()方法报错。

修改方法
protected override void MapToEntity(APJUserDto updateInput, APJUser entity)
{
entity.Name = updateInput.Name;
entity.Gender = updateInput.Gender;
entity.Email = updateInput.Email;
}

至此,一个简单的CURD功能添加完成。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、ABP如何分配权限

在Core项目下,找到PermissionNames.cs这个文件:
在这里插入图片描述
定义一个PermissionName:

 public const string Pages_APJUser_GetAll = "Pages.APJUser.GetAll";

找到Core项目下的AuthorizationProvider.cs文件,并添加一个权限:

context.CreatePermission(PermissionNames.Pages_APJUser_GetAll, L("APJ_User查询权限"));//第二个参数为多资源参数

方法一:
回到APJUserAppService.cs,修改一下查询的方法,在GetAll的方法上添加一个标签:

[AbpAuthorize(PermissionNames.Pages_APJUser_GetAll)]
public override Task<PagedResultDto<APJUserDto>> GetAll(PagedAPJUserResultRequestDto input)
{
    return base.GetAll(input);
}

这时,重新编译整个解决方案,并启动项目。由于admin账号,默认是启动所有的权限,所以我们需要先将admin账号的Pages_APJUser_GetAll权限去掉才可以测试。在Role界面,将Pages_APJUser_GetAll权限去掉。
在这里插入图片描述
这时再调用这个API,则会提示没有权限:
在这里插入图片描述
方法二:
调用PermissionChecker.Authorize()方法

 //[AbpAuthorize(PermissionNames.Pages_APJUser_GetAll)]
public override Task<PagedResultDto<APJUserDto>> GetAll(PagedAPJUserResultRequestDto input)
{
    PermissionChecker.Authorize(PermissionNames.Pages_APJUser_GetAll);       
    return base.GetAll(input);
}

在这里插入图片描述
方法三:
重写CheckGetAllPermission()方法,我们可以看到,ABP默认帮我们实现了很多方法。其中,部分方法是virtual方法,是可以重写的:
在这里插入图片描述
接下来我们重写一下CheckGetAllPermission()方法:

protected override void CheckGetAllPermission()
{
      //业务逻辑
      throw new AbpAuthorizationException("对不起,你没有这个权限");
}

然后,再GetAll()方法中调用。

//[AbpAuthorize(PermissionNames.Pages_APJUser_GetAll)]
public override Task<PagedResultDto<APJUserDto>> GetAll(PagedAPJUserResultRequestDto input)
{
     //PermissionChecker.Authorize(PermissionNames.Pages_APJUser_GetAll);
     CheckGetAllPermission();
     return base.GetAll(input);
}

六、本地资源化

  1. 在Core项目下找到Localization\SourceFiles\APJ.xml
    在这里插入图片描述
  2. 添加一个新的资源:
<text name="TestResource1">This is a test.</text>
  1. 实现:
    方法一:
    在ApplicationService层,注入ILocalizationManager
private ILocalizationManager _localizationManager;

public APJUserAppService(ILocalizationManager localizationManager) : base(repository)
{
      _repository = repository;
      _localizationManager = localizationManager;
}

定义一个接口方法,并实现它:

string GetLozationString(string key, string language);

public string GetLozationString(string key, string language = "en")
{
     return _localizationManager.GetString(APJConsts.LocalizationSourceName, key, new CultureInfo(language));
}
  1. 调用结果:
    在这里插入图片描述

方法二:
再构造函数中初始化 LocalizationSourceName,

public APJUserAppService(IRepository<APJUser, int> repository, ILocalizationManager localizationManager) : base(repository)
{
       _repository = repository;
       _localizationManager = localizationManager;
       LocalizationSourceName = APJConsts.LocalizationSourceName;
}

修改获取多资源的方法:

 public string GetLozationString(string key = "HomePage", string language = "zh-HK")
{
     //return _localizationManager.GetString(APJConsts.LocalizationSourceName, key, new CultureInfo(language));

     return L(key, new CultureInfo(language,false));
}

在这里插入图片描述

七、记录日志

  1. 通过依赖注入,注入Logger对象(注意:仅仅能使用public属性):
  public ILogger Logger { get; set; }

  public APJUserAppService(IRepository<APJUser, int> repository, ILocalizationManager localizationManager) : base(repository)
{
     _repository = repository; 
     _localizationManager = localizationManager;
     LocalizationSourceName = APJConsts.LocalizationSourceName;
     Logger = NullLogger.Instance;
}

  1. 调用:
  Logger.Info("this is a test");

  Logger.Debug("this is debug test");

  Logger.Warn("this is warm test");

得到的结果:(放在Logs.txt文件中)

INFO 2019-10-12 12:05:01,346 [6 ] APJ.APJManagement.APJUserAppService - this is a test
DEBUG 2019-10-12 12:05:01,346 [6 ] APJ.APJManagement.APJUserAppService - this is debug test
WARN 2019-10-12 12:05:01,346 [6 ] APJ.APJManagement.APJUserAppService - this is warm test

  1. 配置log4
    找到Web.Host项目下的log4net.config文件,并打开:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Logs.txt" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
    </layout>
  </appender>
  <root>
    <appender-ref ref="RollingFileAppender" />
    <level value="DEBUG" />
  </root>
</log4net>

详细的配置请参考文章:
https://blog.csdn.net/u013160017/article/details/81392154
https://blog.csdn.net/eagleuniversityeye/article/details/80582140

八、数据验证

方法一:
使用C#自定义标签,如[Required]

[Required]
public string Name { get; set; } 

方法二:
自定义数据验证
实现接口ICustomValidate

    public class CreateAPJUserDto:ICustomValidate
    {
        [Required]
        public string Name { get; set; }

        public string Gender { get; set; }

        public string Email { get; set; }

        public void AddValidationErrors(CustomValidationContext context)
        {
            if (Name.Length>10)
            {
                context.Results.Add(new ValidationResult("Name长度不能大于10"));
            }
        }
    }

结果:
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ABP (ASP.NET Boilerplate) 是一个流行的开源框架,提供了一些常用功能的实现,包括实体框架、用户认证、权限管理等。实现 Word 文档导出可以使用开源库 NPOI。 以下是基本的步骤: 1. 安装 NPOI 包。可以使用 NuGet 命令行工具,输入以下命令: ``` Install-Package NPOI ``` 2. 创建一个类,用于表示要导出的数据。 ``` public class MyData { public string Name { get; set; } public int Age { get; set; } //... } ``` 3. 创建一个方法,用于创建 Word 文档。在该方法中,使用 NPOI 创建一个新的文档,并将数据填充到表格中。 ``` using NPOI.XWPF.UserModel; using NPOI.OpenXmlFormats.Wordprocessing; public void ExportToWord(List<MyData> data) { // Create a new document from scratch XWPFDocument doc = new XWPFDocument(); // Create a table with headers XWPFTable table = doc.CreateTable(data.Count + 1, 2); table.GetRow(0).GetCell(0).SetText("Name"); table.GetRow(0).GetCell(1).SetText("Age"); // Fill in the data for (int i = 0; i < data.Count; i++) { table.GetRow(i + 1).GetCell(0).SetText(data[i].Name); table.GetRow(i + 1).GetCell(1).SetText(data[i].Age.ToString()); } // Save the document to a file FileStream file = new FileStream("output.docx", FileMode.Create); doc.Write(file); file.Close(); } ``` 这个方法将数据填充到一个包含两列的表格中,第一列为“Name”,第二列为“Age”。然后,将文档保存到名为“output.docx”的文件中。 4. 调用导出方法,将数据传递给它。 ``` List<MyData> data = GetDataFromDatabase(); ExportToWord(data); ``` 在这个例子中,我们从数据库中获取数据,并将它传递给导出方法。 这是最基本的示例。你可以根据需要自定义文档的外观和内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值