ABP框架学习笔记

ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。

ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。

官网:http://www.aspnetboilerplate.com

 

1.代码使用的是         2.生成的代码结构是:

3.各层介绍:

SIMS.Core: 领域核心层,是应用程序的核心。该层宝包括业务逻辑和规则。在该层可以定义数据库对象实体,仓储接口等。
SIMS.EntityFramwork: 主要是对数据库表的操作。该层实现Core定义的仓储接口。
SIMS.Applocation: 应用程序层,该层介于Core和展现层(SIMS.Web,SIMS.WebApi)之间。展现层通过它来和服务器交互。该层可以定义DTOS,AutoMapper(仓储实体和数据库实体的转换。),定义IApplocationService接口。(在该层实现IApplicationService的都可以自动生成APIController,供展现层调用。注意,前端调用时候是名字操作的,默认的情况下在该层定义的接口名称要以AppService结尾)
SIMS.Web和SIMS.WebApI组成前端展现层。实现用户交互。

 

4.例子

做一个学历表。表中只有主键和学历名称。

  1.在Core层建一个Entity的文件夹,用来存放数据库实体,并且每个实体类都集成一个叫Entity<PK>的抽象类。该类已经定义了一个主键,主键类型可以是Entity<int>,Entity<long>

public class MajorType:Entity<int>
    {
        public string MajorName { get; set; }
    }

  2.在Core层建一个Repository文件夹,用来定义仓储接口。这些接口都继承现IRepository<T,int>T接口,T表示Entity里面的实体,int/long与实体的主键类型一致。(IRepository已经实现一些基本的方法)

//比如
public
interface IRepository<TEntity, TPrimaryKey> : IRepository, ITransientDependency where TEntity : class, IEntity<TPrimaryKey> { int Count(); int Count(Expression<Func<TEntity, bool>> predicate); Task<int> CountAsync(); Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate); void Delete(TEntity entity); }

public interface IMajorRepository: IRepository<MajorType,int>
{

}

  3.在EntityFramework层下面的EntityFramework==>Repositories定义类实现Core层的仓储接口。该文件下的类都会继承SIMSRepositoryBase<T, int>类,实现Core层的仓库接口。

public class MajorRepository : SIMSRepositoryBase<MajorType, int>, IMajorRepository
    {
        public MajorRepository(IDbContextProvider<SIMSDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }
    }

  4.在Application层建立AppService,IAppService,DTOS,AutoMapper文件夹,用来实现特定的业务逻辑。 

    4.1首先在IAppService文件夹下定义用户交互的接口。该文件夹下的接口都继承IApplicationService接口。

public interface IMajorAppService:IApplicationService
    {
        List<MajorTypeInput> GetAll();

        void InsertorUpdate(MajorTypeInput input);
    }

    4.2在AppService文件夹下定义类来实现IAppService的接口。该文件夹下的类都实现IApplicationService和IAppService文件下的某个接口。注意,在Core层和EntityFrameWork都是但数据表操作,如果对多个表操作,实在该层进行的,通过构造函数注入来操作多表。

public class MajorAppService : IApplicationService, IMajorAppService
    {
        public readonly IMajorRepository _majorRepository;

        public MajorAppService(IMajorRepository majorRepository)
        {
            _majorRepository = majorRepository;
        }
        public List<MajorTypeInput> GetAll()
        {
            var list= _majorRepository.GetAllList();
           
            
            var l= Mapper.Map<List<MajorType>, List<MajorTypeInput>>(list);
            return l;
        }

        public void InsertorUpdate(MajorTypeInput input)
        {
            var l = Mapper.Map<MajorTypeInput, MajorType>(input);
            _majorRepository.InsertOrUpdate(l);
        }
    }

    4.3在DTO文件夹下面简历与展现层交互的input和output,该文件夹下的类实现IInputDto接口。用来进行数据验证,如果想自定义数据验证,还需要实现ICustomValidate接口,在AddValidationErrors(List<ValidationResult> results)方法里面写。

public class MajorTypeInput:IInputDto,ICustomValidate
    {
        public int Id { get; set; }

        [Required]
        public string MajorName { get; set; }
public void AddValidationErrors(List<ValidationResult> results)
    {
        if (SendEmailToAssignedPerson && (!AssignedPersonId.HasValue || AssignedPersonId.Value <= 0))
        {
            results.Add(new ValidationResult("AssignedPersonId must be set if SendEmailToAssignedPerson is true!"));
        }
    }
}

    4.4在AutoMapper文件夹下面建几个类来实现实体自动映射。要转换的实体,将加好的实体类在AutoMapperWebConfig中初始化,然后再app_Start文件夹下的WebModule下的Initialize方法里面添加:AutoMapperWebConfig.Configure();

public class MajorProfile:Profile
    {
        protected override void Configure()
        {
            Mapper.Initialize(cfg => {
                cfg.CreateMap<MajorType, MajorTypeInput>();//type->input
                cfg.CreateMap<MajorTypeInput, MajorType>();//input->type
            });
        }
    }
public static class AutoMapperWebConfig
    {
        public static void Configure()
        {
            Mapper.Initialize(cfg =>
            {
                cfg.AddProfile<MajorProfile>();
                
            });
            Mapper.AssertConfigurationIsValid();//验证所有的映射配置是否都正常
        }
    }
[DependsOn(
        typeof(AbpWebMvcModule),
        typeof(SIMSDataModule), 
        typeof(SIMSApplicationModule), 
        typeof(SIMSWebApiModule),
        typeof(AbpAutoMapperModule))]
   
    public class SIMSWebModule : AbpModule
    {
        public override void PreInitialize()
        {
            //Add/remove languages for your application
            Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
            Configuration.Localization.Languages.Add(new LanguageInfo("tr", "Türkçe", "famfamfam-flag-tr"));
            Configuration.Localization.Languages.Add(new LanguageInfo("zh-CN", "简体中文", "famfamfam-flag-cn"));

            //Add/remove localization sources here
            Configuration.Localization.Sources.Add(
                new DictionaryBasedLocalizationSource(
                    SIMSConsts.LocalizationSourceName,
                    new XmlFileLocalizationDictionaryProvider(
                        HttpContext.Current.Server.MapPath("~/Localization/SIMS")
                        )
                    )
                );

            //Configure navigation/menu
            Configuration.Navigation.Providers.Add<SIMSNavigationProvider>();
        }

        public override void Initialize()
        {
            
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
            AutoMapperWebConfig.Configure();//一次性加载所有映射配置
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

   5.SIMS.WebApi层不需要做任何修改,DynamicApiControllerBuilper提供了建立所有应用层服务的方法比如:

DynamicApiControllerBuilder.ForAll<IApplicationService>(typeof(SIMSApplicationModule).Assembly, "app").Build(); //app 就是路由调用的名字

   5.1当然也可以通过DynamicApiControllerBuilder.For<IxxxAppService>("app").Build();语句来动态的出初始化。如:DynamicApiControllerBuilder.For<IMajorAppService>("app").Build();

   5.2根据以上配置,在上面的APPlication里面建立的IMajorAppService的访问路由就是:/api/services/app/major

   5.3 可以通过单一服务脚本处理:http://localhost:6234/api/abpServiceProxies/Get?name=app/major,代码样式如:

(function(){

    var serviceNamespace = abp.utils.createNamespace(abp, 'services.app.major');

    serviceNamespace.getAll = function(ajaxParams) {
        return abp.ajax($.extend({
            url: abp.appPath + 'api/services/app/major/GetAll',
            type: 'POST',
            data: JSON.stringify({})
        }, ajaxParams));
    };

    serviceNamespace.insertorUpdate = function(input, ajaxParams) {
        return abp.ajax($.extend({
            url: abp.appPath + 'api/services/app/major/InsertorUpdate',
            type: 'POST',
            data: JSON.stringify(input)
        }, ajaxParams));
    };

    if(define && typeof define === 'function' && define.amd){
        define(function (require, exports, module) {
            return {
                getAll: serviceNamespace.getAll,
                insertorUpdate: serviceNamespace.insertorUpdate
            };
        });
    }

})();

 

  6.在SIMS.Controller里面可以访问5的WebAPI接口,代码:

(function () {
    var controllerId = 'app.views.show.show';
    angular.module('app').controller(controllerId, [
             '$scope', 'abp.services.app.major',   //abp.service.app.major要和5的js代码里的ServiceNameSpace一致
             function ($scope, majorService) { //majorService是abp.service.app.major的major+Service组合成,一定要这么写,不然报错
                 var vm = this;
                 vm.major = { id: 0, majorName: '' };
                 vm.getAll = function () {
                     majorService.getAll().success(function (ajaxParams) {
                         vm.majorlist = ajaxParams;
                     });
                 }
                 
                 vm.InsertorUpdate = function () {
                     majorService.insertorUpdate({
                         Id: vm.major.id,
                         MajorName: vm.major.majorName
                     }).success(function () {
                         vm.major.majorName = '';
                         vm.getAll();
                     });
                 }
                 vm.getAll();
             }
    ]);
})();
<div ng-controller="app.views.show.show as vm">
    <table>
        <tr>
            <td>ID</td><td>Majortype</td>
        </tr>
        <tr ng-repeat="item in vm.majorlist">
            <td>{{item.id}}</td>
            <td>{{item.majorName}}</td>
        </tr>
    <tr>
        <td>
            majortype
        </td>
        <td>
            <input type="hidden" ng-model="vm.major.id" />
            <input type="text" ng-model="vm.major.majorName"/>
            <button ng-click="vm.InsertorUpdate()">add</button>
        </td>
    </tr>
    </table>
</div>
<script src="/api/abpServiceProxies/Get?name=app/major" type="text/javascript"></script>

 

在app.js里面添加路由

 app.config([
        '$stateProvider', '$urlRouterProvider',
        function($stateProvider, $urlRouterProvider) {
            $urlRouterProvider.otherwise('/');
            $stateProvider
                .state('home', {
                    url: '/',
                    templateUrl: '/App/Main/views/home/home.cshtml',
                    menu: 'Home' //Matches to name of 'Home' menu in SIMSNavigationProvider
                })
                .state('about', {
                    url: '/about',
                    templateUrl: '/App/Main/views/about/about.cshtml',
                    menu: 'About' //Matches to name of 'About' menu in SIMSNavigationProvider
                }).state('show', {
                    url: '/show',
                    templateUrl: '/App/Main/views/show/show.cshtml',
                    menu: 'show'
                });

        }
    ]);

 

ABP跨域问题

1、在Web Api 项目下安装 Microsoft.AspNet.WebApi.Cors 包

Install-Package Microsoft.AspNet.WebApi.Cors

2、在Web Api 项目下的Module中添加如下两行代码。

var cors = new EnableCorsAttribute("*", "*", "*");
GlobalConfiguration.Configuration.EnableCors(cors);

  

 

posted @ 2016-04-30 20:37  汪汪汪~~  阅读(6287)  评论(0编辑  收藏  举报