Web API 2 入门——使用ASP.NET Web API和Angular.js构建单页应用程序(SPA)(谷歌翻译)

Posted X-JoNNeY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web API 2 入门——使用ASP.NET Web API和Angular.js构建单页应用程序(SPA)(谷歌翻译)相关的知识,希望对你有一定的参考价值。

网络营

下载网络营训练包

在传统的Web应用程序中,客户机(浏览器)通过请求页面启动与服务器的通信。然后,服务器处理请求,并将页面的html发送给客户端。在与页面的后续交互中,用户导航到链接或提交带有数据的表单 - 新的请求将发送到服务器,流程将再次启动:服务器处理请求并将新页面发送到浏览器回应客户要求的新动作。

在单页面应用程序(SPA)中,整个页面在初始请求之后加载到浏览器中,但后续的交互通过Ajax请求进行。这意味着浏览器必须仅更新已更改的页面部分; 没有必要重新加载整个页面。SPA方法减少了应用程序响应用户操作所花费的时间,从而导致更流畅的体验。

SPA的架构涉及传统Web应用程序中不存在的某些挑战。然而,像ASP.NET Web API这样的新兴技术,像AngularJS这样的javascript框架和CSS3提供的新的样式功能使得设计和构建SPA变得非常简单。

在这个动手实验室,您将利用这些技术来实施基于SPA概念的琐事网站Geek Quiz。您将首先使用ASP.NET Web API实现服务层,以公开所需的端点,以检索测验问题并存储答案。然后,您将使用AngularJS和CSS3转换效果构建一个丰富和响应的UI。

所有示例代码和代码段都包含在Web Camps Training Kit中,可从http://aka.ms/webcamps-trainingkit获取

概观

 

目标

在这个动手实验中,您将学习如何:

  • 创建一个ASP.NET Web API服务来发送和接收JSON数据
  • 使用AngularJS创建响应式UI
  • 通过CSS3转换增强UI体验

 

先决条件

完成此动手实验室需要以下内容:

 

建立

为了在这个动手实验室中运行练习,你需要首先设置你的环境。

  1. 打开Windows资源管理器并浏览实验室的“ 源”文件夹。
  2. 右键单击Setup.cmd,然后选择以管理员身份运行,启动安装过程,该过程将配置您的环境并安装本实验的Visual Studio代码片段。
  3. 如果显示“用户帐户控制”对话框,请确认该操作继续。
注意

在运行安装程序之前,请确保已经检查了该实验室的所有依赖项。

 

使用代码片段

在整个实验室文档中,将指示您插入代码块。为方便起见,这些代码大部分作为Visual Studio代码片段提供,您可以从Visual Studio 2013中访问,以避免手动添加。

注意

每个练习都附有一个起始解决方案,位于练习Begin文件夹中,可以让您独立于其他练习进行每项练习。请注意,在这些开始的解决方案中缺少在练习期间添加的代码段,并且在完成练习之前可能无法正常工作。在练习的源代码中,您还将找到一个包含Visual Studio解决方案End文件夹,其中包含完成相应练习中的步骤所产生的代码。您可以使用这些解决方案作为指导,如果您需要额外的帮助,当您通过这个动手实验室。


 

演习

这个动手实验室包括以下练习:

  1. 创建Web API
  2. 创建SPA界面

预计完成本实验的时间:60分钟

注意

当您第一次启动Visual Studio时,您必须选择一个预定义的设置集合。每个预定义的集合都被设计为匹配特定的开发风格,并确定窗口布局,编辑器行为,智能感知代码片段和对话框选项。本实验中的过程描述了在使用“ 常规开发设置”集合时在Visual Studio中完成给定任务所需的操作如果您为开发环境选择不同的设置集合,那么您应该考虑的步骤可能会有所不同。

 

练习1:创建Web API

SPA的关键部分之一是服务层。它负责处理由UI发送的Ajax调用,并响应于该调用返回数据。检索的数据应以机器可读格式呈现,以便客户端进行解析和使用。

Web API框架是ASP.NET堆栈的一部分,旨在使HTTP服务变得容易,通常通过RESTful API发送和接收JSON或XML格式的数据。在本练习中,您将创建Web站点来托管Geek Quiz应用程序,然后实施后端服务,以使用ASP.NET Web API公开并保留测验数据。

 

任务1 - 创建Geek测验的初始项目

在此任务中,您将开始创建一个新的ASP.NET MVC项目,并支持基于Visual Studio附带一个ASP.NET项目类型的ASP.NET Web API 一个ASP.NET统一了所有的ASP.NET技术,并提供了根据需要进行混合和匹配的选项。然后,您将添加实体框架的模型类和数据库初始化器以插入测验问题。

  1. 打开Visual Studio Express 2013 for Web,然后选择File | 新项目...开始一个新的解决方案。

    技术分享

    创建新项目

  2. 在“ 新建项目”对话框中,Visual C#|选择ASP.NET Web应用程序 网页标签。确保选择了.NET Framework 4.5,将其命名为GeekQuiz,选择位置,然后单击确定

    技术分享

    创建一个新的ASP.NET Web应用程序项目

  3. 在“ 新建ASP.NET项目”对话框中,选择MVC模板并选择Web API选项。此外,请确保“ 身份验证”选项设置为“ 个人用户帐户”单击确定继续。

    技术分享

    使用MVC模板创建一个新项目,包括Web API组件

  4. 解决方案资源管理器中,右键单击GeekQuiz项目Models文件夹,然后选择Add | 现有项...

    技术分享

    添加现有项目

  5. 在“ 添加现有项目”对话框中,导航到“ 源/资产/模型”文件夹,然后选择所有文件。单击添加

    技术分享

    添加模型资产

    注意

    通过添加这些文件,您将添加数据模型,Entity Framework的数据库上下文和Geek Quiz应用程序的数据库初始化程序。

    实体框架(EF)是一种对象关系映射器(ORM),它使您能够通过使用概念应用程序模型编程创建数据访问应用程序,而不是直接使用关系存储架构进行编程。您可以在这里了解有关实体框架的更多信息

    以下是刚刚添加的类的描述:

    • TriviaOption:表示与测验问题相关联的单个选项
    • TriviaQuestion:表示一个测验问题,并通过Options属性公开相关选项
    • TriviaAnswer:表示用户响应测验问题选择的选项
    • TriviaContext:代表实体框架的Geek Quiz应用程序的数据库环境。该类派生自DContext,并公开表示上述实体的集合的DbSet属性。
    • TriviaDatabaseInitializer:实现了继承自CreateDatabaseIfNotExistsTriviaContext的Entity Framework初始化器此类的默认行为是仅在不存在的情况下创建数据库,才能插入“ 种子”方法中指定的实体
  6. 打开Global.asax.cs文件并添加以下using语句。

    C#
    using GeekQuiz.Models;
    
  7. Application_Start方法的开头添加以下代码,TriviaDatabaseInitializer设置为数据库初始化程序。

    C#
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            System.Data.Entity.Database.SetInitializer(new TriviaDatabaseInitializer()); 
    
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
    
  8. 修改Home控制器以限制对经过身份验证的用户的访问。为此,请打开Controllers文件夹中HomeController.cs文件,并将Authorize属性添加HomeController类定义。

    C#
    namespace GeekQuiz.Controllers
    {
        [Authorize]
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            ...
        }
    }
    
    注意

    授权过滤器检查,看是否该用户进行身份验证。如果用户未通过身份验证,则返回HTTP状态码401(未经授权),而不调用该操作。您可以在全局,控制器级别或单个操作级别应用过滤器。

  9. 您现在将自定义网页的布局和品牌。为此,请Views |中打开_Layout.cshtml文件 通过使用Geek Quiz替换My ASP.NET应用程序共享文件夹并更新<title>元素的内容

    CSHTML
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - Geek Quiz</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    
    </head>
    
  10. 在同一个文件中,通过删除关于联系人链接并将主页链接重命名播放更新导航栏另外,重命名应用程序名称链接到Geek Quiz导航栏的HTML应如下所示。

    CSHTML
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Geek Quiz", "Index", "Home", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Play", "Index", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    
  11. 通过使用Geek Quiz替换“ 我的ASP.NET应用程序”更新布局页面的页脚为此,请使用以下突出显示的代码替换<footer>元素的内容。

    HTML
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - Geek Quiz</p>
        </footer>
    </div>
    

 

任务2 - 创建TriviaController Web API

在上一个任务中,您创建了Geek Quiz Web应用程序的初始结构。您现在将构建一个简单的Web API服务,它与测验数据模型进行交互,并公开以下操作:

  • GET / api / trivia:从测验列表中检索下一个问题,由认证用户回答。
  • POST / api / trivia:存储由验证的用户指定的测验答案。

您将使用Visual Studio提供的ASP.NET脚手架工具为Web API控制器类创建基准。

  1. 打开App_Start文件夹中WebApiConfig.cs文件。该文件定义了Web API服务的配置,就像路由映射到Web API控制器操作一样。
  2. 在文件开头添加以下using语句。

    C#
    using Newtonsoft.Json.Serialization;
    
  3. 将以下突出显示的代码添加到Register方法中,以全局配置Web API操作方法检索的JSON数据的格式化程序。

    C#
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            // Use camel case for JSON data.
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    
    注意

    CamelCasePropertyNamesContractResolver自动属性名称转换为骆驼的情况下,这是在JavaScript属性名称的一般惯例。

  4. 解决方案资源管理器中,右键单击GeekQuiz项目Controllers文件夹,然后选择Add | 新搭建的项目......

    技术分享

    创建一个新的脚手架物品

  5. 在“ 添加脚手架”对话框中,确保在左侧窗格中选择了“ 公共”节点。然后,在中央窗格中选择Web API 2控制器 - 空模板,然后单击添加

    技术分享

    选择Web API 2控制器空模板

    注意

    ASP.NET脚手架是ASP.NET Web应用程序的代码生成框架。Visual Studio 2013包括用于MVC和Web API项目的预安装代码生成器。当您希望快速添加与数据模型交互的代码,以减少开发标准数据操作所需的时间,您应该在项目中使用脚手架。

    脚手架过程还确保所有所需的依赖关系都安装在项目中。例如,如果您从一个空的ASP.NET项目开始,然后使用脚手架来添加一个Web API控制器,则所需的Web API NuGet软件包和引用将自动添加到您的项目中。

  6. 在“ 添加控制器”对话框中,在“ 控制器名称”文本框中键入TriviaController然后单击“ 添加”

    技术分享

    添加Trivia控制器

  7. 然后TriviaController.cs文件添加到GeekQuiz项目Controllers文件夹中,其中包含一个空的TriviaController类。在文件的开头添加以下使用语句。

    (代码片段 - AspNetWebApiSpa - Ex1 - TriviaControllerUsings

    C#
    using System.Data.Entity;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http.Description;
    using GeekQuiz.Models;
    
  8. TriviaController的开头添加以下代码,以便在控制器中定义,初始化和处理TriviaContext实例。

    (代码片段 - AspNetWebApiSpa - Ex1 - TriviaControllerContext

    C#
    public class TriviaController : ApiController
    {
        private TriviaContext db = new TriviaContext();
    
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.db.Dispose();
            }
    
            base.Dispose(disposing);
        }
    }
    
    注意

    处置的方法TriviaController调用处置所述的方法TriviaContext例如,这确保了在由所述上下文对象中使用的所有资源被释放TriviaContext实例设置或垃圾收集。这包括关闭Entity Framework打开的所有数据库连接。

  9. TriviaController的末尾添加以下帮助方法此方法从数据库中检索以下问题以由指定的用户回答。

    (代码片段 - AspNetWebApiSpa - Ex1 - TriviaControllerNextQuestion

    C#
    private async Task<TriviaQuestion> NextQuestionAsync(string userId)
    {
        var lastQuestionId = await this.db.TriviaAnswers
            .Where(a => a.UserId == userId)
            .GroupBy(a => a.QuestionId)
            .Select(g => new { QuestionId = g.Key, Count = g.Count() })
            .OrderByDescending(q => new { q.Count, QuestionId = q.QuestionId })
            .Select(q => q.QuestionId)
            .FirstOrDefaultAsync();
    
        var questionsCount = await this.db.TriviaQuestions.CountAsync();
    
        var nextQuestionId = (lastQuestionId % questionsCount) + 1;
        return await this.db.TriviaQuestions.FindAsync(CancellationToken.None, nextQuestionId);
    }
    
  10. 将以下Get操作方法添加TriviaController类中。此操作方法调用上一步中定义NextQuestionAsync帮助器方法来检索已验证用户的下一个问题。

    (代码片段 - AspNetWebApiSpa - Ex1 - TriviaControllerGetAction

    C#
    // GET api/Trivia
    [ResponseType(typeof(TriviaQuestion))]
    public async Task<IHttpActionResult> Get()
    {
        var userId = User.Identity.Name;
    
        TriviaQuestion nextQuestion = await this.NextQuestionAsync(userId);
    
        if (nextQuestion == null)
        {
            return this.NotFound();
        }
    
        return this.Ok(nextQuestion);
    }
    
  11. TriviaController的末尾添加以下帮助方法该方法将指定的答案存储在数据库中,并返回一个布尔值,指示答案是否正确。

    (代码片段 - AspNetWebApiSpa - Ex1 - TriviaControllerStoreAsync

    C#
    private async Task<bool> StoreAsync(TriviaAnswer answer)
    {
        this.db.TriviaAnswers.Add(answer);
    
        await this.db.SaveChangesAsync();
        var selectedOption = await this.db.TriviaOptions.FirstOrDefaultAsync(o => o.Id == answer.OptionId
            && o.QuestionId == answer.QuestionId);
    
        return selectedOption.IsCorrect;
    }
    
  12. 将以下Post操作方法添加TriviaController类中。此操作方法将答案与经过身份验证的用户相关联,并调用StoreAsync帮助程序方法。然后,它发送一个响应与由辅助方法返回的布尔值。

    (代码段 - AspNetWebApiSpa - Ex1 - TriviaControllerPostAction

    C#
    // POST api/Trivia
    [ResponseType(typeof(TriviaAnswer))]
    public async Task<IHttpActionResult> Post(TriviaAnswer answer)
    {
        if (!ModelState.IsValid)
        {
            return this.BadRequest(this.ModelState);
        }
    
        answer.UserId = User.Identity.Name;
    
        var isCorrect = await this.StoreAsync(answer);
        return this.Ok<bool>(isCorrect);
    }
    
  13. 修改Web API控制器以通过将授权属性添加TriviaController类定义来限制对经过身份验证的用户的访问

    C#
    [Authorize]
    public class TriviaController : ApiController
    {
        ...
    }
    

 

任务3 - 运行解决方案

在此任务中,您将验证您在前一任务中构建的Web API服务是否按预期工作。您将使用Internet Explorer F12开发人员工具捕获网络流量并检查Web API服务的完整响应。

注意

确保在Visual Studio工具栏上的“ 开始”按钮中选择了Internet Explorer

技术分享

  1. F5运行解决方案。在登录页面应该出现在浏览器中。

    注意

    当应用程序启动时,默认的MVC路由被触发,默认情况下映射到HomeControllerIndex操作由于HomeController仅限于经过身份验证的用户(请记住,您使用练习1中Authorize属性来修饰该类),并且还没有用户认证,应用程序将原始请求重定向到登录页面。

    技术分享

    运行解决方案

  2. 单击注册以创建新用户。

    技术分享

    注册新用户

  3. 注册页面中,输入用户名密码,然后单击注册

    技术分享

    注册页面

  4. 应用程序注册新帐户,用户被认证并重新定向到主页。

    技术分享

    用户进行身份验证

  5. 在浏览器中,按F12打开“ 开发人员工具”面板。CTRL + 4或单击网络图标,然后单击绿色箭头按钮开始捕获网络流量。

    技术分享

    启动Web API网络捕获

  6. 在浏览器地址栏中的URL 附加api / trivia您现在将从TriviaController中Get操作方法检查响应的详细信息

    技术分享

    通过Web API检索下一个问题数据

    注意

    一旦下载完成,系统将提示您对下载的文件进行操作。让对话框打开,以便能够通过开发人员工具窗口来观看响应内容。

  7. 现在你将检查身体的反应。为此,请单击详细信息选项卡,然后单击响应正文您可以检查下载的数据是否与具有对应于TriviaQuestion的属性选项(它是TriviaOption对象的列表),id标题的对象

    技术分享

    查看Web API响应体

  8. 返回到Visual Studio,然后按SHIFT + F5停止调试。

 

练习2:创建SPA界面

在本练习中,您将首先构建Geek Quiz的Web前端部分,重点介绍使用AngularJS的单页应用程序交互然后,您将通过CSS3增强用户体验,以执行丰富的动画,并在从一个问题转换到下一个问题时提供上下文切换的视觉效果。

 

任务1 - 使用AngularJS创建SPA接口

在这个任务中,您将使用AngularJS来实现Geek Quiz应用程序的客户端。AngularJS是一个开放源码的JavaScript框架,通过模型 - 视图 - 控制器(MVC)功能来增强基于浏览器的应用程序,有助于开发和测试。

您将首先从Visual Studio的软件包管理器控制台安装AngularJS。然后,您将创建控制器以提供Geek Quiz应用程序的行为和使用AngularJS模板引擎呈现测验问题和答案的视图。

注意

有关AngularJS的更多信息,请参阅[http://angularjs.org/](http://angularjs.org/))

  1. 打开Visual Studio Express 2013 for Web,并打开位于Source / Ex2-CreatingASPAInterface / Begin文件夹中GeekQuiz.sln解决方案或者,您可以继续在上一个练习中获得的解决方案。
  2. 工具 | 打开包管理器控制台 图书馆包裹经理键入以下命令来安装AngularJS.Core NuGet包。

    电源外壳
    Install-Package AngularJS.Core
    
  3. 解决方案资源管理器中,右键单击GeekQuiz项目脚本文件夹,然后选择添加 新建文件夹命名文件夹应用程序,然后按Enter键
  4. 右键单击刚刚创建应用程序文件夹,然后选择添加| JavaScript文件

    技术分享

    创建一个新的JavaScript文件

  5. 在“ 指定项目名称”对话框中,在“ 项目名称”文本框中键入quiz-controller然后单击“ 确定”

    技术分享

    命名新的JavaScript文件

  6. quiz-controller.js文件中,添加以下代码来声明和初始化AngularJS QuizCtrl控制器。

    (代码片段 - AspNetWebApiSpa - Ex2 - AngularQuizController

    JavaScript的
    angular.module(‘QuizApp‘, [])
        .controller(‘QuizCtrl‘, function ($scope, $http) {
            $scope.answered = false;
            $scope.title = "loading question...";
            $scope.options = [];
            $scope.correctAnswer = false;
            $scope.working = false;
    
            $scope.answer = function () {
                return $scope.correctAnswer ? ‘correct‘ : ‘incorrect‘;
            };
        });
    
    注意

    QuizCtrl控制器的构造函数需要一个名为$ scope的可注射参数应在构造函数中通过将属性附加到$ scope对象来设置范围的初始状态属性包含视图模型,并且在注册控制器时可以访问模板。

    所述QuizCtrl控制器被命名模块中定义QuizApp模块是工作单元,可以将您的应用程序分解成单独的组件。使用模块的主要优点是代码更容易理解,便于单元测试,可重用性和可维护性。

  7. 您现在将向作用域添加行为,以便对从视图触发的事件作出反应。QuizCtrl控件的末尾添加以下代码,以定义$ scope对象中nextQuestion函数

    (代码片段 - AspNetWebApiSpa - Ex2 - AngularQuizControllerNextQuestion

    JavaScript的
    .controller(‘QuizCtrl‘, function ($scope, $http) { 
        ...
    
        $scope.nextQuestion = function () {
            $scope.working = true;
            $scope.answered = false;
            $scope.title = "loading question...";
            $scope.options = [];
    
            $http.get("/api/trivia").success(function (data, status, headers, config) {
                $scope.options = data.options;
                $scope.title = data.title;
                $scope.answered = false;
                $scope.working = false;
            }).error(function (data, status, headers, config) {
                $scope.title = "Oops... something went wrong";
                $scope.working = false;
            });
        };
    };
    
    注意

    此函数从上一个练习中创建Trivia Web API中检索下一个问题,并将问题数据附加到$ scope对象。

  8. QuizCtrl控件的末尾插入以下代码,以定义$ scope对象中sendAnswer函数

    (代码片段 - AspNetWebApiSpa - Ex2 - AngularQuizControllerSendAnswer

    JavaScript的
    .controller(‘QuizCtrl‘, function ($scope, $http) { 
        ...
    
        $scope.sendAnswer = function (option) {
            $scope.working = true;
            $scope.answered = true;
    
            $http.post(‘/api/trivia‘, { ‘questionId‘: option.questionId, ‘optionId‘: option.id }).success(function (data, status, headers, config) {
                $scope.correctAnswer = (data === true);
                $scope.working = false;
            }).error(function (data, status, headers, config) {
                $scope.title = "Oops... something went wrong";
                $scope.working = false;
            });
        };
    };
    
    注意

    此功能将用户选择的答案发送到Trivia Web API,并存储结果,如果答案是否正确,则在$ scope对象中。

    上述的NextQuestionsendAnswer函数使用AngularJS $ http对象通过浏览器中的XMLHttpRequest JavaScript对象抽象与Web API的通信。AngularJS支持另一种服务,它通过RESTful API为资源执行CRUD操作提供了更高的抽象级别。AngularJS $资源对象具有提供高级行为的操作方法,而不需要与$ http对象进行交互考虑在需要CRUD模型的场景中使用$资源对象(前提信息,请参阅$资源文档)。

  9. 下一步是创建定义测验视图的AngularJS模板。为此,请Views |中打开Index.cshtml文件 文件夹,并用以下代码替换内容。

    (Code Snippet - AspNetWebApiSpa - Ex2 - GeekQuizView

    CSHTML
    @{
        ViewBag.Title = "Play";
    }
    
    <div id="bodyContainer" ng-app="QuizApp">
        <section id="content">
            <div class="container" >
                <div class="row">
                    <div class="flip-container text-center col-md-12" ng-controller="QuizCtrl" ng-init="nextQuestion()">
                        <div class="back" ng-class="{flip: answered, correct: correctAnswer, incorrect:!correctAnswer}">
                            <p class="lead">{{answer()}}</p>
                            <p>
                                <button class="btn btn-info btn-lg next option" ng-click="nextQuestion()" ng-disabled="working">Next Question</button>
                            </p>
                        </div>
                        <div class="front" ng-class="{flip: answered}">
                            <p class="lead">{{title}}</p>
                            <div class="row text-center">
                                <button class="btn btn-info btn-lg option" ng-repeat="option in options" ng-click="sendAnswer(option)" ng-disabled="working">{{option.title}}</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
    
    @section scripts {
        @Scripts.Render("~/Scripts/angular.js")
        @Scripts.Render("~/Scripts/app/quiz-controller.js")
    }
    
    注意

    AngularJS模板是一个声明性规范,它使用模型信息和控制器将静态标记转换为用户在浏览器中看到的动态视图。以下是可以在模板中使用的AngularJS元素和元素属性的示例:

    • NG-应用指令告诉AngularJS代表应用程序的根元素的DOM元素。
    • NG-控制器指令附加一个控制器在其中指令申报点的DOM。
    • 大括号符号{{}}表示绑定到控制器中定义的范围属性。
    • NG-点击指令用于调用响应于用户点击在范围中定义的功能。
  10. 打开Content文件夹中Site.css文件,并在文件末尾添加以下突出显示的样式,以提供测验视图的外观。

    (代码片段 - AspNetWebApiSpa - Ex2 - GeekQuizStyles

    CSS
    .validation-summary-valid {
         display: none;
    }
    
    /* Geek Quiz styles */
    .flip-container .back,
    .flip-container .front {
         border: 5px solid #00bcf2;
         padding-bottom: 30px;
         padding-top: 30px;
    }
    
    #content {
        position:relative;
        background:#fff;
        padding:50px 0 0 0;
    }
    
    .option {
         width:140px;
         margin: 5px;
    }
    
    div.correct p {
         color: green;
    }
    
    div.incorrect p {
         color: red;
    }
    
    .btn {
         border-radius: 0;
    }
    
    .flip-container div.front, .flip-container div.back.flip {
        display: block;
    }
    
    .flip-container div.front.flip, .flip-container div.back {
        display: none;
    }
    

 

任务2 - 运行解决方案

在此任务中,您将使用您使用AngularJS构建的新用户界面来执行解决方案,以回答一些测验问题。

  1. F5运行解决方案。
  2. 注册一个新的用户帐号。为此,请按照练习1,任务3中所述的注册步骤进行操作。

    注意

    如果您使用上一个练习中的解决方案,您可以使用之前创建的用户帐户登录。

  3. 主页页面应该出现,显示了测验的第一个问题。通过单击其中一个选项来回答问题。这将触发先前定义sendAnswer函数,该函数将选定的选项发送到Trivia Web API。

    技术分享

    回答一个问题

  4. 点击其中一个按钮后,应该会出现答案。单击下一个问题以显示以下问题。这将触发控制器中定义nextQuestion函数。

    技术分享

    请求下一个问题

  5. 下一个问题应该出现。继续多次回答问题。完成所有问题后,您应该回到第一个问题。

    技术分享

    下一个问题

  6. 返回到Visual Studio,然后按SHIFT + F5停止调试。

 

任务3 - 使用CSS3创建翻转动画

在这个任务中,您将使用CSS3属性来执行丰富的动画,通过在问题回答和下一个问题被检索时添加翻转效果。

  1. 解决方案资源管理器中,右键单击GeekQuiz项目的“ 内容”文件夹,然后选择“ 添加” 现有项...

    技术分享

    将现有项目添加到“内容”文件夹

  2. 在“ 添加现有项目”对话框中,导航到“ 源/资源”文件夹,然后选择“ Flip.css”单击添加

    技术分享

    从资产添加Flip.css文件

  3. 打开刚刚添加Flip.css文件并检查其内容。
  4. 找到翻转变换注释。该评论下方的样式使用CSS 透视图rotateY转换来生成“卡片翻转”效果。

    CSS
    /* flip transformation */
    .flip-container div.front {
        -moz-transform: perspective(2000px) rotateY(0deg);
        -webkit-transform: perspective(2000px) rotateY(0deg);
        -o-transform: perspective(2000px) rotateY(0deg);
        transform: perspective(2000px) rotateY(0deg);
    }
    
        .flip-container div.front.flip {
            -moz-transform: perspective(2000px) rotateY(179.9deg);
            -webkit-transform: perspective(2000px) rotateY(179.9deg);
            -o-transform: perspective(2000px) rotateY(179.9deg);
            transform: perspective(2000px) rotateY(179.9deg);
        }
    
    .flip-container div.back {
        -moz-transform: perspective(2000px) rotateY(-180deg);
        -webkit-transform: perspective(2000px) rotateY(-180deg);
        -o-transform: perspective(2000px) rotateY(-180deg);
        transform: perspective(2000px) rotateY(-180deg);
    }
    
        .flip-container div.back.flip {
            -moz-transform: perspective(2000px) rotateY(0deg);
            -webkit-transform: perspective(2000px) rotateY(0deg);
            -ms-transform: perspective(2000px) rotateY(0);
            -o-transform: perspective(2000px) rotateY(0);
            transform: perspective(2000px) rotateY(0);
        }
    
  5. 在翻盖评论期间找到窗格隐藏通过将背景可见性 CSS属性设置为隐藏,该注释下方的样式通过将背面可见性 CSS属性设置为隐藏,从而隐藏了面部背面的背面

    CSS
    /* hide back of pane during flip */
    .front, .back {
        -moz-backface-visibility: hidden;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
    }
    
  6. 打开App_Start文件夹中BundleConfig.cs文件,并将引用添加到“?/ Content / css”样式包中Flip.css文件

    C#
    bundles.Add(new StyleBundle("~/Content/css").Include(
        "~/Content/bootstrap.css",
        "~/Content/site.css",
        "~/Content/Flip.css"));
    
  7. F5运行解决方案并使用凭据登录。
  8. 通过点击其中一个选项来回答问题。注意在视图之间转换时的翻转效果。

    技术分享

    回答一个具有翻转效果的问题

  9. 单击下一个问题以检索以下问题。翻转效果应再次出现。

    技术分享

    使用翻转效果检索以下问题


 

概要

通过完成这个动手实验,你已经学会了如何:

  • 使用ASP.NET脚手架创建一个ASP.NET Web API控制器
  • 实施Web API获取操作以检索下一个测验问题
  • 实施Web API Post操作来存储测验答案
  • 从Visual Studio包管理器控制台安装AngularJS
  • 实施AngularJS模板和控制器
  • 使用CSS3转换来执行动画效果
 

以上是关于Web API 2 入门——使用ASP.NET Web API和Angular.js构建单页应用程序(SPA)(谷歌翻译)的主要内容,如果未能解决你的问题,请参考以下文章

01Getting Started---Getting Started with ASP.NET Web API 2入门WebApi2

Web API1.1 ASP.NET Web API入门

Web API 2 入门——使用ASP.NET Web API和Angular.js构建单页应用程序(SPA)(谷歌翻译)

ASP.NET Web API入门介绍

ASP.NET-入门

Asp.Net Web API 2第五课——Web API路由