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);

