Asp.net MVC Api项目搭建

整个解决方案按照分层思想来划分不同功能模块,以提供User服务的Api为需求,各个层次的具体实现如下所示:

1、新建数据库User表

数据库使用SQLExpress版本,表的定义如下所示:

sql 复制代码
CREATE TABLE [dbo].[User] (
    [Id]               INT           IDENTITY (1, 1) NOT NULL,
    [Name]             NVARCHAR (50) NOT NULL,
    [Password]         NVARCHAR (50) NOT NULL,
    [Age]              INT           NOT NULL,
    [Birthdate]        DATE          NOT NULL,
    [CreateTime]       DATETIME      DEFAULT (getdate()) NOT NULL,
    [CreateUserId]     NVARCHAR (50) NOT NULL,
    [CreateUserName]   NVARCHAR (50) NOT NULL,
    [ModifiedTime]     DATETIME      NULL,
    [ModifiedUserId]   NVARCHAR (50) NULL,
    [ModifiedUserName] NVARCHAR (50) NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)
);

2、实体层

新建类库类型的项目,.net framework框架版本4.5,User实体类如下:

cs 复制代码
public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }
        public int Age { get; set; }
        public DateTime Birthdate { get; set; }
        public DateTime CreateTime { get; set; }
        public string CreateUserId { get; set; }
        public string CreateUserName { get; set; }
        public DateTime? ModifiedTime { get; set; }
        public string ModifiedUserId { get; set; }
        public string ModifiedUserName { get; set; }
    }

3、数据库层

该层提供数据库接口操作,采用EntitFramework4.4.0.0作为ORM实体映射框架,

  • 定义数据库操作接口IRepository
cs 复制代码
public interface IRepository<TEntity> : IDisposable where TEntity : class
    {
        IEnumerable<TEntity> Get();
        IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter);
        IEnumerable<TEntity> Get<TOderKey>(Expression<Func<TEntity, bool>> filter, int pageIndex, int pageSize, Expression<Func<TEntity, TOderKey>> sortKeySelector, bool isAsc = true);

        int Count(Expression<Func<TEntity, bool>> predicate);
        void Update(TEntity instance);
        void Add(TEntity instance);
        void Delete(TEntity instance);
    }
  • 定义数据库上下文类BceDbContext
cs 复制代码
public class BceDbContext:DbContext
    {
        public BceDbContext():base("DaLeiDB")
        {
            Database.SetInitializer<AceDbContext>(null);
        }
        public DbSet<User> Users { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>().ToTable("User");
            base.OnModelCreating(modelBuilder);
        }
    }
  • 定义数据库通用操作实现类BceRepository
cs 复制代码
public class BceRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        public BceDbContext DbContext { get; private set; }
        public DbSet<TEntity> DbSet { get; private set; }
        public BceRepository(BceDbContext context)
        {
            Guard.ArgumentNotNull(context, "context");
            this.DbContext = context;
            this.DbSet = this.DbContext.Set<TEntity>();
        }

        public IEnumerable<TEntity> Get()
        {
            return this.DbSet.AsQueryable();
        }
        public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter)
        {
            return this.DbSet.Where(filter).AsQueryable();
        }
        public IEnumerable<TEntity> Get<TKey>(Expression<Func<TEntity, bool>> filter, int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> sortKeySelector, bool isAsc = true)
        {
            Guard.ArgumentNotNull(filter, "predicate");
            Guard.ArgumentNotNull(sortKeySelector, "sortKeySelector");
            if (isAsc)
            {
                return this.DbSet
                    .Where(filter)
                    .OrderBy(sortKeySelector)
                    .Skip(pageSize * (pageIndex - 1))
                    .Take(pageSize).AsQueryable();
            }
            else
            {
                return this.DbSet
                    .Where(filter)
                    .OrderByDescending(sortKeySelector)
                    .Skip(pageSize * (pageIndex - 1))
                    .Take(pageSize).AsQueryable();
            }
        }

        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            return this.DbSet.Where(predicate).Count();
        }

        public void Add(TEntity instance)
        {
            Guard.ArgumentNotNull(instance, "instance");
            this.DbSet.Attach(instance);
            this.DbContext.Entry(instance).State = EntityState.Added;
            this.DbContext.SaveChanges();
        }
        public void Update(TEntity instance)
        {
            Guard.ArgumentNotNull(instance, "instance");
            this.DbSet.Attach(instance);
            this.DbContext.Entry(instance).State = EntityState.Modified;
            this.DbContext.SaveChanges();
        }
        public void Delete(TEntity instance)
        {
            Guard.ArgumentNotNull(instance, "instance");
            this.DbSet.Attach(instance);
            this.DbContext.Entry(instance).State = EntityState.Deleted;
            this.DbContext.SaveChanges();
        }

        public void Dispose()
        {
            this.DbContext.Dispose();
        }
    }
  • 定义用户表数据库操作额外的接口IUserRepository
cs 复制代码
namespace DaLei.Repository
{
    public interface IUserRepository
    {
        User FindByName(string name);
        List<User> FindByAge(int start, int end);
    }
}
  • 定义用户表数据库操作额外的实现类UserRepository

    cs 复制代码
    namespace DaLei.Repository
    {
        public class UserRepository : BceRepository<User>, IUserRepository
        {
            public UserRepository(BceDbContext bceDbContext):base(bceDbContext)
            {
    
            }
    
            public List<User> FindByAge(int start, int end)
            {
                var rst = this.DbSet.AsQueryable().Where(u=>u.Age>=start && u.Age<=end).ToList();
                return rst;
            }
    
            public User FindByName(string name)
            {
                var rst = this.DbSet.AsQueryable().Where(u => u.Name == name).FirstOrDefault();
                return rst;
            }
        }
    }

4、服务接口层

定义了对外提供用户服务的接口契约,具体如下:

cs 复制代码
namespace DaLei.IService
{
    public interface IUserService
    {
        User FindByName(string name);
        List<User> FindByAge(int start, int end);
        List<User> GetList();
    }
}

5、服务具体实现层

服务基类实现:

cs 复制代码
using System;
using System.Collections.Generic;

namespace DaLei.Service
{
    public abstract class ServiceBase : IDisposable
    {
        public IList<IDisposable> DisposableObjects { get; private set; }
        public ServiceBase()
        {
            this.DisposableObjects = new List<IDisposable>();
        }
        protected void AddDisposableObject(object obj)
        {
            IDisposable disposable = obj as IDisposable;
            if (null != disposable)
            {
                this.DisposableObjects.Add(disposable);
            }
        }

        public void Dispose()
        {
            foreach (IDisposable obj in this.DisposableObjects)
            {
                if (null != obj)
                {
                    obj.Dispose();
                }
            }
        }
    }
}

用户服务接口具体实现:

cs 复制代码
using DaLei.IService;
using DaLei.Model;
using DaLei.Repository;
using System.Collections.Generic;

namespace DaLei.Service
{
    public class UserService : ServiceBase,IUserService
    {
        private IUserRepository userRepository;
        public UserService(IUserRepository userRepository)
        {
            this.userRepository = userRepository;
            this.AddDisposableObject(userRepository);
        }
        public List<User> FindByAge(int start, int end)
        {
            return this.userRepository.FindByAge(start,end);
        }

        public User FindByName(string name)
        {
            return this.userRepository.FindByName(name);
        }

        public List<User> GetList()
        {
            return this.userRepository.FindByAge(0, 100);
        }
    }
}

6、应用层

新建Asp.net WebApi项目,引用服务接口项目、服务实现项目、实体类项目,unity相关程序集,EntityFramework程序集。

web.config配置连接字符串和unity相关内容:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
    <containers>
      <container>
        <extension type="Interception" />
        <register type="DaLei.IService.IUserService, DaLei.IService" mapTo="DaLei.Service.UserService, DaLei.Service" />
        <register type="DaLei.Repository.IUserRepository, DaLei.Repository" mapTo="DaLei.Repository.UserRepository, DaLei.Repository">
          <interceptor type="InterfaceInterceptor" />
          <policyInjection />
        </register>
      </container>
    </containers>
  </unity>
  <connectionStrings>
    <add name="DaLeiDB" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=DaleiDB;User ID=sa;Password=anpiel0991;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0"/>
    <add key="webpages:Enabled" value="false"/>
    <add key="PreserveLoginUrl" value="true"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5"/>
    <httpRuntime targetFramework="4.5"/>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers"/>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Web.WebPages"/>
      </namespaces>     
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler"/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler"
        preCondition="integratedMode,runtimeVersionv4.0"/>
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"/>
        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
</configuration>
  • Controller实例化由Unity负责处理,需要实现控制器工厂类
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace WebApi.Extensions
{
    public class UnityControllerFactory : DefaultControllerFactory
    {
        static object syncHelper = new object();
        static Dictionary<string, IUnityContainer> containers = new Dictionary<string, IUnityContainer>();
        public IUnityContainer UnityContainer { get; private set; }
        public UnityControllerFactory(string containerName = "")
        {
            if (containers.ContainsKey(containerName))
            {
                this.UnityContainer = containers[containerName];
                return;
            }
            lock (syncHelper)
            {
                if (containers.ContainsKey(containerName))
                {
                    this.UnityContainer = containers[containerName];
                    return;
                }
                IUnityContainer container = new UnityContainer();
                //配置UnityContainer
                UnityConfigurationSection configSection = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;
                if (null == configSection && !string.IsNullOrEmpty(containerName))
                {
                    throw new ConfigurationErrorsException("The <unity> configuration section does not exist.");
                }
                if (null != configSection)
                {
                    if (string.IsNullOrEmpty(containerName))
                    {
                        configSection.Configure(container);
                    }
                    else
                    {
                        configSection.Configure(container, containerName);
                    }
                }
                containers.Add(containerName, container);
                this.UnityContainer = containers[containerName];
            }
        }
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (null == controllerType)
            {
                return null;
            }
            return (IController)this.UnityContainer.Resolve(controllerType);
        }
//public override void ReleaseController(IController controller)
//{
//    this.UnityContainer.Teardown(controller);
//}
    }
}
  • 设置MVC框架的控制器工厂为自定义类型
cs 复制代码
using webApi.Extensions;
using System;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;

namespace WebApp
{
    public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            // 在应用程序启动时运行的代码
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());
        }
    }
}
  • 新建Controller基类,所有的自定义Controller均继承此类
cs 复制代码
using WebApi.Extensions;
using System.Web.Mvc;
using System;
using System.Collections.Generic;

namespace WebApp.Controllers
{
    public class BaseController:Controller
    {
        public IList<IDisposable> DisposableObjects { get; private set; }
        public BaseController()
        {
            this.DisposableObjects = new List<IDisposable>();
        }
        protected void AddDisposableObject(object obj)
        {
            IDisposable disposable = obj as IDisposable;
            if (null != disposable)
            {
                this.DisposableObjects.Add(disposable);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                foreach (IDisposable obj in this.DisposableObjects)
                {
                    if (null != obj)
                    {
                        obj.Dispose();
                    }
                }
            }
            base.Dispose(disposing);
        }
    }
}
  • 新建测试Controller
cs 复制代码
using DaLei.IService;
using System.Web.Mvc;

namespace WebApp.Controllers
{
    public class TestController : BaseController
    {
        private IUserService userService;
        public TestController(IUserService userService)
        {
            this.userService = userService;
            this.AddDisposableObject(userService);
        }

        // GET: Test
        public ActionResult Index()
        {
            var users = this.userService.GetList();
            return View();
        }
    }
}

浏览器输入地址测试TestController!

相关推荐
阑梦清川1 天前
SpringMVC案例学习(二)--表白墙/图书管理系统1.0版本
spring·mvc·springboot·案例
网安_秋刀鱼1 天前
PHP代码审计 --MVC模型开发框架&rce示例
开发语言·web安全·网络安全·php·mvc·1024程序员节
HaiFan.2 天前
Spring MVC
java·spring·mvc
源码12152 天前
Asp.net Mvc 电脑销售系统
后端·asp.net·mvc
计算机毕设定制辅导-无忧学长2 天前
《深入理解 Spring MVC 工作流程》
java·spring·mvc
潜洋3 天前
Spring Boot教程之三:Spring Boot 与 Spring MVC 及 Spring的区别
java·spring boot·spring·mvc
清酒伴风(面试准备中......)3 天前
Spring MVC——针对实习面试
java·后端·spring·面试·mvc·实习
ac-er88884 天前
ThinkPHP6的ORM模型
开发语言·php·mvc
计算机学姐4 天前
基于Python的招聘信息推荐系统
开发语言·vue.js·python·mysql·pycharm·django·mvc
Ai 编码助手4 天前
Spring MVC 中是如何保证Controller的并发安全?
安全·spring·mvc