登录完成后,我们继续来完成余下的功能。本文要完成的是文章管理功能,主要包括后台应用层服务以及客户端存储(Store)的数据访问调整。
由于本文涉及的类很多,因而,只挑了一些比较有代表性的类来讲解,其余的,有兴趣可以自行下载代码来研究,或者发私信、评论等方式咨询我。
一般情况下,数据传输对象会定义在应用服务文件夹(Application项目)的Dto内,如Categories\Dto用来存放文章分类的数据传输对象。类的命名规则是[使用该类的方法名称][实体名称][输入或输出]Dto,如GetAllCategoryInputDto,GetAll就是使用的该类的方法名,Category就是实体名称,Input表示这是输入对象。
在ABP中,为我们预定义了一些Dto对象和接口,从他们派生可以实现一些特定功能,如PagedAndSortedResultRequestDto就为请求提供了分页和排序等接口,包括SkipCount(要跳过的记录数)、MaxResultCount(获取的最大记录数)和Sorting(排序信息)等属性。要查看具体有那些具体对象或接口,可以查看ABP框架源代码内的src\Abp\Application\Services\Dto文件夹。
在调用Get方法时,都会将实体的所有可曝露的数据返回到客户端,因而,在开始的时候都会为Get方法定义一个基本的数据传输对象,如以下的ContentDto类:
[AutoMapFrom(typeof(Content))]
public class ContentDto :EntityDto
{
[Required]
[MaxLength(Content.MaxStringLength)]
public string Title { get; set; }
[Required]
public long CategoryId { get; set; }
[MaxLength(Content.MaxStringLength)]
public string Image { get; set; }
[MaxLength(Content.MaxSummaryLength)]
public string Summary { get; set; }
[Required]
public string Body { get; set; }
[Required]
public int Hits { get; set; }
[Required]
public int SortOrder { get; set; }
public DateTime CreationTime { get; set; }
}
代码中,AutoMapFrom特性表示该对象会从Content实体中获取数据填充类的属性。反过来,如果要将提交的数据转换为实体,可使用AutoMapTo特性。由于该类主要是将实体转换为返回数据,因而代码中的验证特性MaxLength、Required等可以不定义。
由于在Content中包含两个长度比较长的文本字段,在调用GetAll方法时并不希望将这些字段返回到客户端,因而需要定义一个GetAllContentOutputDto类作为GetAll方法的返回对象,具体代码如下:
[AutoMapFrom(typeof(Content))]
public class GetAllContentOutputDto : EntityDto
{
public string Title { get; set; }
public long CategoryId { get; set; }
public string CategoryTitle { get; set; }
public int Hits { get; set; }
public int SortOrder { get; set; }
public DateTime CreationTime { get; set; }
public string[] Tags { get; set; }
}
在代码中,CategoryTitle和Tags在Content实体中并没有对应的属性,因而这个需要在应用服务中再进行填充。
对于GetAll方法,除了分页和排序信息,还会提交查询信息,因而,需要定义一个GetAllContentInputDto类来处理提交,具体代码如下:
public class GetAllContentInputDto : PagedAndSortedResultRequestDto, IShouldNormalize
{
private readonly JObject _allowSorts = new JObject()
{
{ "id", "Id" },
{ "title", "Title" },
{ "creationTime", "CreationTime" },
{ "sortOrder", "SortOrder" },
{ "hits", "Hits" }
};
public long Cid { get; set; }
public string Query { get; set; }
public DateTime? StartDateTime { get; set; }
public DateTime? EndDateTime { get; set; }
[CanBeNull]
public string Sort { get; set; }
public void Normalize()
{
if (!string.IsNullOrEmpty(Sort))
{
Sorting = ExtJs.OrderBy(Sort, _allowSorts);
}
}
}
由于Ext JS的存储(Store)不能将排序字段和排序方向合并到一个字段提交,因而,为了处理方便,特意定义了Sort属性来接收提交数据,然后再转换为Sor