一步步创建基于React+EF6+WebApi2+Gulp的项目

一、相关技术

  1. Onion Architecture
  2. Flux、Alt.js
  3. ReactJS.Net
  4. MiniProfiler EF 6
  5. React-Bootstrap
  6. StructureMap
  7. PostSharp
  8. AutoMapping
  9. Moq、Nunit
  10. Jenkin
  11. Gulp、NodeJS
  12. Mehdime.Entity
  13. Enyim.Caching

二、项目目录

关于Onion Structure?

一步步创建基于React+EF6+WebApi2+Gulp的项目_第1张图片

三、DB层创建

1. 创建执行sql

一步步创建基于React+EF6+WebApi2+Gulp的项目_第2张图片

Use [master]
go

IF NOT EXISTS (select name from master..syslogins where name='TemplateUser') 
BEGIN
    CREATE LOGIN [TemplateUser]
           WITH PASSWORD=N'pwd123',
           DEFAULT_DATABASE=[Template],
           DEFAULT_LANGUAGE=[us_english],
           CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF

    ALTER LOGIN [TemplateUser] ENABLE
END


--== Add CapitalStructureAppUser login to DB ==--
USE [Template]
CREATE USER [TemplateUser] FOR LOGIN [TemplateUser];
EXEC sp_addrolemember 'db_owner', 'TemplateUser'
GO

USE [Template]
GO
--============================================================--
--==                    Drop objects                        ==--
--============================================================--
IF EXISTS (SELECT TOP 1 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Users')
   DROP TABLE [dbo].[Users]
GO
--============================================================--
--==                    Create Objcets                      ==--
--============================================================--
CREATE TABLE [dbo].[Users](
    [UserID] [INT] IDENTITY(1,1) NOT NULL,
    [Name] [NVARCHAR](255) NOT NULL,
    [ModifiedBy] [NVARCHAR](128) NOT NULL CONSTRAINT [DF_User_ModifiedBy] DEFAULT ('SYSTEM'),
    [ModifiedAt] [DATETIME] NOT NULL CONSTRAINT [DF_User_ModifiedAt] DEFAULT (GETDATE()),
    CONSTRAINT [PK_User_UserID] PRIMARY KEY CLUSTERED ([UserID]) ON [PRIMARY],
    CONSTRAINT [UX_User_Name] UNIQUE NONCLUSTERED ([Name]) ON [PRIMARY]
) ON [PRIMARY]
GO
View Code

2. 使用Mehdime.Entity创建DbContext相关

  关于Mehdime.Entity?

一步步创建基于React+EF6+WebApi2+Gulp的项目_第3张图片

Nuget上下载mehdime.entity,将对应文件复制到如下图

创建接口文件

一步步创建基于React+EF6+WebApi2+Gulp的项目_第4张图片

创建Implementations文件

一步步创建基于React+EF6+WebApi2+Gulp的项目_第5张图片

3. 创建DomainModel - User

一步步创建基于React+EF6+WebApi2+Gulp的项目_第6张图片

public class User: ModelBase
    {
        public User() {
        }
        [Key]
        public int UserId { get; set; }
        [Required]
        public string Name { get; set; }
    }
View Code

4. 创建项目Context- TemplateContext

using System.Data.Entity;
    using System.Data.Common;
    using Domain.Models.Accounts;

    public class TemplateContext : DbContext
    {
        public TemplateContext() :base("name=Template") {
            Configuration.ProxyCreationEnabled = false;
        }

        public TemplateContext(DbConnection connection)
            : base(connection, false)
        {
            Configuration.ProxyCreationEnabled = false;
        }

        public virtual DbSet<User> Users { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            #region Table Name Mapping

            modelBuilder.Entity<User>().ToTable("User");

            #endregion
        }
    }
View Code

三、Repository

1、创建Repository工厂

public interface IRepository<TEntity> where TEntity : class
    {
        IQueryable<TEntity> Query();

        void Add(TEntity entity);

        void Update(TEntity entity);

        void Delete(TEntity entity);
    }


public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        private readonly DbContext _context;
        protected readonly IDbSet<TEntity> EntitySet;

        public Repository(DbContext context)
        {
            _context = context;
            EntitySet = _context.Set<TEntity>();
        }

        public IQueryable<TEntity> Query()
        {
            return EntitySet;
        }

        public void Add(TEntity entity)
        {
            throw new NotImplementedException();
        }

        public void Update(TEntity entity)
        {
            throw new NotImplementedException();
        }

        public void Delete(TEntity entity)
        {
            throw new NotImplementedException();
        }
    }
View Code

2、扩展DbContextExtensions

  扩展DbContext,用于获取当前Repository

public static class DbContextExtensions
    {
        public static IRepository<TEntity> GetRepository<TEntity>(this DbContext context) where TEntity : class
        {
            return new Repository<TEntity>(context);
        }
    }
View Code

3、创建AccountRepository

日志接口暂时忽略ILoggerService

public interface IAccountRepository
    {
        IEnumerable<User> GetUsers();
    }

public class AccountRepository: ContextRepository, IAccountRepository
    {
        private readonly ILoggerService _logger;

        public AccountRepository(IAmbientDbContextLocator contextLocator, ILoggerService logger) : base(contextLocator)
        {
            _logger = logger;
        }

        public IEnumerable<User> GetUsers()
        {
            var dbUsers = Context.GetRepository<User>().Query().ToList();
            return dbUsers;
        }
    }
View Code

四、Services

创建对应的接口和类

1、接口

public interface IAccountService
    {
        IEnumerable<User> GetAllUsers(User requestingUser);
    }
View Code

2、服务类

 public class AccountService : IAccountService
    {
        private readonly IAccountRepository _accountRepository;
        private readonly IDbContextScopeFactory _dbContextScopeFactory;

        public AccountService(IDbContextScopeFactory dbContextScopeFactory, IAccountRepository accountRepository)
        {
            _accountRepository = accountRepository;
            _dbContextScopeFactory = dbContextScopeFactory;
        }

        public IEnumerable<User> GetAllUsers(User requestingUser)
        {
            if (requestingUser == null)
            {
                throw new ArgumentNullException("requestingUser");
            }

            using (_dbContextScopeFactory.CreateReadOnly())
            {
                var userCollection = _accountRepository.GetUsers();
                return userCollection;
            }
        }
    }
View Code

五、API

引用api的RoutePrefix需要更改System.Web.http引用路径,如下

<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
    </Reference>
View Code

1、创建基类AppApiController

  用于获取当前User用户

public class AppApiController: ApiController
    {
        public User RequestUser
        {
            get { return (Domain.Models.Accounts.User) User; }
        }
    }
View Code

2、扩展ApiController

  用于对结果数据进行统一封装和装饰,如mapper功能等。 Mapper功能后续补上

  首先,创建自定义的IHttpActionResult返回结果。

  a. 返回成功类

public class ApiFailActionResult : IHttpActionResult
    {
        private readonly string Message;

        public ApiFailActionResult(string message)
        {
            Message = message;
        }

        public Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
        {
            return Task.FromResult(ExecuteResult());
        }

        public HttpResponseMessage ExecuteResult()
        {
            var response = new HttpResponseMessage(HttpStatusCode.BadRequest);

            var Data = new
            {
                Success = false,
                Data = (object)null,
                Error = Message
            };

            var settings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                Converters = new JsonConverter[]
                {
                    new StringEnumConverter()
                }
            };

            var jsonString = JsonConvert.SerializeObject(Data, settings);

            response.Content = new StringContent(jsonString);
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            return response;
        }
View Code

  b. 返回失败类

public class ApiFailActionResult : IHttpActionResult
    {
        private readonly string Message;

        public ApiFailActionResult(string message)
        {
            Message = message;
        }

        public Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
        {
            return Task.FromResult(ExecuteResult());
        }

        public HttpResponseMessage ExecuteResult()
        {
            var response = new HttpResponseMessage(HttpStatusCode.BadRequest);

            var Data = new
            {
                Success = false,
                Data = (object)null,
                Error = Message
            };

            var settings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                Converters = new JsonConverter[]
                {
                    new StringEnumConverter()
                }
            };

            var jsonString = JsonConvert.SerializeObject(Data, settings);

            response.Content = new StringContent(jsonString);
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            return response;
        }
    }
View Code

  c. 扩展ApiController

public static class ApiControllerExtension
    {
        public static ApiOkActionResult ApiOkResult(this ApiController controller)
        {
            return new ApiOkActionResult(null);
        }

        public static ApiOkActionResult ApiOkResult<TResponseType>(this ApiController controller, object data)
        {
            if (data == null)
            {
                return ApiOkResult(controller);
            }
            //var mappedData = Mapper.Map<TResponseType>(data);

            return new ApiOkActionResult(data);
        }

        public static ApiFailActionResult ApiFailResult(this ApiController controller, string message)
        {
            return new ApiFailActionResult(message);
        }
    }
View Code

3、 添加一个Api方法

View Code

六、DI的引用-IOC容器StructureMap

 关于StructureMap的相关介绍和说明,可参照博文http://www.cnblogs.com/XmNotes/archive/2012/01/09/2317255.html,本文只阐明如何用到当前Project上。

 未完待续.....

你可能感兴趣的:(一步步创建基于React+EF6+WebApi2+Gulp的项目)