65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 AngularJS 和 Web API 构建员工跟踪器 – 第 1 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2017 年 1 月 31 日

CPOL

6分钟阅读

viewsIcon

14879

这是使用 AngularJS 和 ASP.NET Web API 系列构建员工跟踪器的第一部分。

这是使用 AngularJS 和 ASP.NET Web API 系列构建员工跟踪器的第一部分。您将学习如何

本教程系列的源代码已发布在 GitHub 上。演示应用程序托管在 Microsoft Azure 上。

第 1 部分:使用 C# 创建 Web API 应用程序

在本教程中,我们将使用 Visual Studio 2013 和 SQL Server 为这个单页应用程序奠定基础。

服务器端技术

任务 1. 创建初始解决方案和项目

  1. 右键单击 Visual Studio 2013 并选择 以管理员身份运行 来启动 Visual Studio。然后,从 开始 页面选择 新建项目。或者,从 文件 菜单中选择 新建,然后选择 项目… 来启动一个新解决方案。

  2. 新建项目 对话框中,在 Visual C# 选项卡下选择 ASP.NET Web 应用程序。确保选中了 .NET Framework 4.5,将其命名为 EmployeeTracker.Api,将 解决方案名称 设置为 EmployeeTrackerRS,选择一个 位置,然后单击 确定

    Creating a new ASP.NET Web Application project

    EmployeeTracker.Api 包含 Web API Restful 接口的控制器。

  3. 新建 ASP.NET 项目 对话框中,选择 Empty 模板。在 为以下项添加文件夹和核心引用 下选择 Web API 选项。确保 身份验证 选项设置为 无身份验证。单击 确定 继续。

    Creating a new project with the Empty template

  4. 解决方案资源管理器 中,右键单击 EmployeeTrackerRS 解决方案,然后选择 添加,然后选择 新建项目…

    Creating a new project

  5. 添加新项目 对话框中,在 Visual C# 选项卡下选择 类库。确保选中了 .NET Framework 4.5,将其命名为 EmployeeTracker.Services,然后单击 确定

    Creating a new Class Library project

    EmployeeTracker.Services 封装了数据访问层,并包含检索数据并将其映射到数据模型​​的逻辑。

  6. EmployeeTracker.Service 项目中,右键单击 Class1.cs 文件并选择 删除 以移除该文件。

  7. 解决方案资源管理器 中,右键单击 EmployeeTrackerRS 解决方案,然后选择 属性

  8. 解决方案“EmployeeTrackerRS”属性页 对话框中,在 通用属性 选项卡下选择 启动项目。确保为 EmployeeTracker.Api 选择了 单个启动项目

    Setting a Single startup project

  9. 在同一个 解决方案“EmployeeTrackerRS”属性页 对话框中,在 通用属性 选项卡下选择 项目依赖项。将 项目 设置为 EmployeeTracker.Api。在 依赖于: 下选择 EmployeeTracker.Services 的复选框,然后单击 确定

    Setting a Project Dependencies

  10. 解决方案资源管理器 中,右键单击 EmployeeTracker.Api 项目,然后选择 属性

  11. EmployeeTracker.Api 窗格中,选择 Web 选项卡。确保选中了 本地 IIS,并将 项目 URL 设置为 https:///employee-tracker-apis。单击 创建虚拟目录

    Creating IIS Virtual Directory

  12. 让我们重新构建应用程序。在 解决方案资源管理器 中,右键单击 EmployeeTrackerRS 解决方案,然后选择 重新生成解决方案

任务 2. 为每个项目安装所需的 NuGet 包

  1. 程序包管理器控制台 中,将 EmployeeTracker.Api 选择为 默认项目。将 nugget.org 选择为 程序包源

     

    Install-Package Autofac -Version 3.5.0	
    Install-Package Autofac.WebApi2 –Version 3.4.0
    Install-Package Microsoft.AspNet.Cors –Version 5.2.3
    Install-Package Microsoft.AspNet.WebApi.Cors –Version 5.2.3

     

    在第 1 行输入上面的 Install-Package 命令,然后按 Enter 键。重复此步骤,直到您完成所有四个程序包的安装。

    Installing a package to EmployeeTracker.Api project

  2. 程序包管理器控制台 中,将 EmployeeTracker.Services 选择为 默认项目。将 nugget.org 选择为 程序包源

     

    Install-Package Dapper -Version 1.42

     

    在第 1 行输入上面的 Install-Package 命令,然后按 Enter 键。

    Installing a package to EmployeeTracker.Services project

  3. 解决方案资源管理器 中,右键单击 EmployeeTrackerRS 解决方案,然后选择 启用 NuGet 程序包还原。单击 继续。

    Enabling NuGet Package Restore

任务 3. 在 EmployeeTracker.Services 项目中创建数据模型和服务

我偶然发现了 Joe Sauve 写的这篇关于如何使用 Dapper 异步访问数据库的文章:文章。Dapper 还支持许多不同的数据库供应商。考虑到这一点,您可以重构以下类以支持 SQL Server 以外的其他数据库。

  1. 解决方案资源管理器 中,右键单击 EmployeeTracker.Services 项目,然后选择 添加,然后选择 新建文件夹。将文件夹命名为 Common

    Create a new folder

  2. 右键单击新创建的 Common 文件夹。从上下文菜单中,选择 添加,然后选择 新项…

    Creating a new item

  3. 添加新项 对话框中,在 Visual C# 项 选项卡下选择 接口。将其命名为 IConnection.cs,然后单击 添加

    Creating an interface

    用以下内容替换生成的代码

     

    namespace EmployeeTracker.Services.Common
    {
        public interface IConnection
        {
            string ConnectionString { get; }
        }
    }

     

  4. 再次,右键单击 Common 文件夹。从上下文菜单中,选择 添加,然后选择 新项…。在 添加新项 对话框中,在 Visual C# 项 选项卡下选择 。将其命名为 Connection.cs,然后单击 添加

    Creating a class

    通过添加实现 IConnection 接口的 Connection 类来替换生成的代码

     

    using System;
    using System.Configuration;
    
    namespace EmployeeTracker.Services.Common
    {
        public class Connection: IConnection
        {
            public Connection(ConnectionStringSettings settings)
            {
                // must use a guard clause to ensure something is injected
                if (settings == null)
                    throw new ArgumentNullException("settings", "Connection expects constructor injection for connectionStringSettings param.");
    
                // we have a value by now so assign it
                ConnectionString = settings.ConnectionString;
            }
    
            public string ConnectionString { get; set; }
    
        }
    }

     

    Connection 类包含 SQL Server 数据库的连接设置。

  5. 创建一个名为 SqlServer 的新文件夹。将 IRepository 接口添加到此文件夹。用以下内容替换生成的代码

     

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Threading.Tasks;
    
    namespace EmployeeTracker.Services.SqlServer
    {
        public interface IRepository
        {
            Task<T> WithConnection<T>(Func<IDbConnection, Task<T>> getData);
            SqlConnection GetConnection(bool multipleActiveResultSets = false);
        }
    }

     

    接下来,添加实现 IRepository 接口的 Repository

     

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using EmployeeTracker.Services.Common;
    
    namespace EmployeeTracker.Services.SqlServer
    {
        public class Repository: IRepository
        {
            private readonly string _connectionString;
    
            public Repository(IConnection db)
            {
                _connectionString = db.ConnectionString;
            }
    
            // use for buffered queries that return a type
            public async Task<T> WithConnection<T>(Func<IDbConnection, Task<T>> getData)
            {
                try
                {
                    using (var connection = new SqlConnection(_connectionString))
                    {
                        await connection.OpenAsync();
                        return await getData(connection);
                    }
                }
                catch (TimeoutException ex)
                {
                    throw new TimeoutException("Timeout Exception", ex);
                }
                catch (SqlException ex)
                {
                    throw new DBConcurrencyException("Sql Exception", ex);
                }
            }
    
            public SqlConnection GetConnection(bool multipleActiveResultSets = false)
            {
                try
                {
                    var cs = _connectionString;
                    if (multipleActiveResultSets)
                    {
                        var scsb = new SqlConnectionStringBuilder(cs) { MultipleActiveResultSets = true };
                        if (scsb.ConnectionString != null) cs = scsb.ConnectionString;
                    }
                    var connection = new SqlConnection(cs);
                    connection.Open();
                    return connection;
                }
                catch (TimeoutException ex)
                {
                    throw new TimeoutException("Timeout Exception", ex);
                }
                catch (SqlException ex)
                {
                    throw new DBConcurrencyException("Sql Exception", ex);
                }
            }
    
        }
    }

     

    这个 Repository 类实现了 Joe 的 WithConnection() 方法来异步管理数据库连接的打开、数据访问和关闭。

  6. 解决方案资源管理器 中,右键单击 EmployeeTracker.Services 项目,然后选择 添加,然后选择 引用…

  7. 引用管理器 对话框中,在 程序集 选项卡下选择 框架。选中 System.Configuration 的复选框,然后单击 确定

  8. 重新生成解决方案。

任务 4. 在 EmployeeTracker.Api 项目中注册所有服务

接下来,我们将使用 Autofac 作为 IoC 容器,它将处理我们所有依赖项的生命周期管理并为我们进行依赖项注入。

控制反转的思想是,与其将应用程序中的类耦合在一起,让类“实例化”它们的依赖项,不如反转过来,在类构造期间将依赖项传递进来。
Autofac

遵循文档中关于如何将 Autofac 集成到我们的应用程序中的说明,我们需要创建一个 ContainerBuilder,然后注册我们的类以在此基础上公开它们的接口。

  1. EmployeeTracker.Api 项目中,打开 App_Start 文件夹中的 WebApiConfig.cs 文件。用以下内容替换生成的代码

     

    using System.Reflection;
    using System.Web.Http;
    using Autofac;
    using Autofac.Integration.WebApi;
    using EmployeeTracker.Api.Autofac;
    using Newtonsoft.Json.Serialization;
    using System.Web.Http.Cors;
    
    namespace EmployeeTracker.Api
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API configuration and services
    
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                // use camel case for JSON data
                config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
                  new CamelCasePropertyNamesContractResolver();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
    
                /*** Autofac: Build the container ***/
                var builder = new ContainerBuilder(); 
    
                // register Web API Controllers
                builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
    
                // register your classes and expose their interfaces - shared
                builder.RegisterModule(new StandardModule()); 
    
                var container = builder.Build();
                config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            }
        }
    }

     

  2. 创建一个名为 Autofac 的新文件夹。将 StandardModule 类添加到此文件夹。用以下内容替换生成的代码

     

    using System.Configuration;
    using Autofac;
    using EmployeeTracker.Services.Common;
    using EmployeeTracker.Services.SqlServer;
    
    namespace EmployeeTracker.Api.Autofac
    {
        public class StandardModule: Module
        {
            protected override void Load(ContainerBuilder builder)
            {
                base.Load(builder);
    
                // obtain database connection string once and reuse by Connection class
                var conn = ConfigurationManager.ConnectionStrings["DBConnection"];
    
                // Register Connection class and expose IConnection 
                // by passing in the Database connection information
                builder.RegisterType<Connection>() // concrete type
                    .As<IConnection>() // abstraction
                    .WithParameter("settings", conn)
                    .InstancePerLifetimeScope();
    
                // Register Repository class and expose IRepository
                builder.RegisterType<Repository>() 
                    .As<IRepository>() 
                    .InstancePerLifetimeScope();
            }
        }
    }

     

  3. 解决方案资源管理器 中,右键单击 EmployeeTracker.Api 项目,然后选择 添加,然后选择 引用…

  4. 引用管理器 对话框中,单击 浏览… 按钮。

  5. 选择要引用的文件… 对话框中,找到并选择 EmployeeTracker.Services.dll。单击 添加,然后单击 确定

  6. 重新生成解决方案。

任务 5. 运行 SQL 脚本来创建数据库、表和存储过程

  1. 启动 SQL Server 2014 Management Studio。然后,连接到数据库服务器。

  2. 文件 菜单中,选择 打开,然后选择 文件…

    Opening File in SQL Server

  3. 打开文件 对话框中,选择 EmployeeTracker db.sql,然后单击 打开。您可以从 Github 下载 EmployeeTracker db.sql

    Choosing File in SQL Server

  4. 确保选择了 Master。单击 执行 以创建 EmployeeTrackerRS 的数据库、表和存储过程。

    Executing SQL Script

在本教程中,我们刚刚完成了员工跟踪器 Web API 应用程序的初始结构的创建。在下一个教程中,我们将构建 Web API 服务。

本教程系列的源代码已发布在 GitHub 上。演示应用程序托管在 Microsoft Azure 上。

参考文献

这篇 Build an Employee Tracker with AngularJS and Web API – Part 1 文章最先出现在 CC28 Technology

© . All rights reserved.