如何在 ASP.NET MVC 中集成 AngularJS(3)

今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容。

调试路由表 - HTML 缓存清除

就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表:一个运行在调试模式的应用程序下和一个运行在发布模式的应用程序下。在调试模式下,JavaScript 文件在未使用压缩功能的情况下会被下载。如果想要调试并在 JavaScript 控制器中设置断点,这是必须的。事实上,路由表的产生版本也出现了一些挑战,由于产生路由代码使用的是 JavaScript 捆绑,但是在 Visual Studio 下,捆绑无法一步一步执行调试,所以我无法调试这些代码。我不得不将一些 console.log 命令和一些 JavaScript 语句警报一起开发并测试来生成路由表。

两个路由版本都包含的事情是:支持 HTML 文件的缓存,就像捆绑和 JavaScript,你还需要提供一个附属在 HTML Angular 视图上的序列号。在调试和生成路由代码两种情况下,嵌入版本号将会从 applicationConfigurationProvder 中推出并附属在缓存的 HTML 路径中。

// CodeProjectRouting-debug.js


angular.module("codeProject").config(

['$routeProvider', '$locationProvider', 'applicationConfigurationProvider',


    function ($routeProvider, $locationProvider, applicationConfigurationProvider) {


    this.getApplicationVersion = function () {

        var applicationVersion = applicationConfigurationProvider.getVersion();

        return applicationVersion;

    }


    var baseSiteUrlPath = $("base").first().attr("href");

   

    $routeProvider.when('/:section/:tree',

    {

        templateUrl: function (rp) { return baseSiteUrlPath + 'views/' + 

                     rp.section + '/' + rp.tree + '.html?v=' + this.getApplicationVersion(); },


        resolve: {


            load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {


                var path = $location.path().split("/");

                var directory = path[1];

                var controllerName = path[2];

               

                var controllerToLoad = "Views/" + directory + "/" + 

                    controllerName + "Controller.js?v=" + this.getApplicationVersion();


                var deferred = $q.defer();


                require([controllerToLoad], function () {

                    $rootScope.$apply(function () {

                        deferred.resolve();

                    });

                });


                return deferred.promise;

              

            }]

        }


    });


    $routeProvider.when('/:section/:tree/:id',

    {

        templateUrl: function (rp) { return baseSiteUrlPath + 'views/' + 

                     rp.section + '/' + rp.tree + '.html?v=' + this.getApplicationVersion(); },


        resolve: {


            load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {


                var path = $location.path().split("/");

                var directory = path[1];

                var controllerName = path[2];


                var controllerToLoad = "Views/" + directory + "/" + controllerName + 

                                       "Controller.js?v=" + this.getApplicationVersion();


                var deferred = $q.defer();


                require([controllerToLoad], function () {

                    $rootScope.$apply(function () {

                        deferred.resolve();

                    });

                });


                return deferred.promise;


            }]

        }


    });


    $routeProvider.when('/',

    {


        templateUrl: function (rp) { return baseSiteUrlPath + 'views/Home/Index.html?v=' + 

                                     this.getApplicationVersion(); },


        resolve: {


            load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {


                var controllerToLoad = "Views/Home/IndexController.js?v=" + 

                                        this.getApplicationVersion();


                var deferred = $q.defer();


                require([controllerToLoad], function () {

                    $rootScope.$apply(function () {

                        deferred.resolve();

                    });

                });


                return deferred.promise;


            }]

        }


    });


    $locationProvider.html5Mode(true);  


}]);

测试浏览器缓存

当开发一个 Web 应用程序时,一件你想要做的事情是:测试所有浏览器的缓存和缓存清除功能。你将会想要确保你的应用内容被正确下载并缓存,这些内容会在页面请求之后出现。

你将会对你的内容做很多改变,来重建你的应用,以确保清除缓存和内容被再次下载时新版本号的问题能够解决。

为了测试这一切,我在发布模式下通过 Chrome 浏览器来运行应用,并点击 F12 来打开网络标签。在这里,你可以看见下载你的应用花费了多少时间和来自于服务器的内容,或者是浏览器的缓存。你甚至可以看到捆绑包的下载情况。

最终,你点击你的应用程序的所有页面,你会发现,所有的内容是从浏览器缓存来了,这是单页应用的美丽之处。你的所有内容都会以获取更大的缓存响应时间为结束,唯一要做的点击 web 服务器来从呈现在页面中的 RESTful Web API 来返回 JSON 格式的数据。

 

其它有趣的点 

其它实例应用中有趣的点,还包括执行在服务器端的 .NET 库。对于数据的有效性输入,应用在业务处理中使用了 FluentValidation 库。 

FluentValidation 是 .NET 的一个使用流畅的界面和 lambda 表达式建立验证规则的小型验证库。

当试图创建示例应用程序的客户时,客户代码和公司名称为必填项。示例应用程序的业务层管理有效性,使用了 FluentValidation 库验证。通过将一个密集的客户对象传入到 CreateCustomer 方法中,对象上的属性可以通过设置的 FluentValidation 表达式的业务规则被验证。如果该业务对象验证失败,业务层可以从验证库返回错误的集合,并发送错误收集结果到客户端,以便浏览器端错误信息的呈现。

public Customer CreateCustomer(Customer customer, out TransactionalInformation transaction)

{

     transaction = new TransactionalInformation();


     try

     {

         CustomerBusinessRules customerBusinessRules = new CustomerBusinessRules();

         ValidationResult results = customerBusinessRules.Validate(customer);


         bool validationSucceeded = results.IsValid;

         IList<ValidationFailure> failures = results.Errors;


         if (validationSucceeded == false)

         {

             transaction = ValidationErrors.PopulateValidationErrors(failures);

             return customer;

         }


         _customerDataService.CreateSession();

         _customerDataService.BeginTransaction();

         _customerDataService.CreateCustomer(customer);

         _customerDataService.CommitTransaction(true);


         transaction.ReturnStatus = true;

         transaction.ReturnMessage.Add("Customer successfully created.");


    }

    catch (Exception ex)

    {

         string errorMessage = ex.Message;

         transaction.ReturnMessage.Add(errorMessage);

         transaction.ReturnStatus = false;

    }

    finally

    {

        _customerDataService.CloseSession();

    }


    return customer;

}

下面是定义了客户对象的业务规则类,使用 FluentValidation 库,定义一组 lambda 表达式并创建业务规则和每个验证相关的错误信息。该 FluentValidation 库使用了一组不同的 lambda 表达式来验证业务对象或实体。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using FluentValidation;

using CodeProject.Business.Entities;

using System.Configuration;

using CodeProject.Interfaces;


namespace CodeProject.Business

{

    public class CustomerBusinessRules : AbstractValidator<Customer>

    {


        public CustomerBusinessRules()

        {       

            RuleFor(c => c.CompanyName).NotEmpty().WithMessage("Company Name is required.");

            RuleFor(c => c.CustomerCode).NotEmpty().WithMessage("Customer Code is required.");   

        }


    }


}

在示例应用程序中另一个值得注意的点,是使用 Ninject 库的依赖注入的实现。当 Ninject从NuGet 安装时,一个配置文件 NinjectWebCommon.cs 就会为你创建。在这里,你可以告诉 Ninject 库当应用的某些部分被执行时,要创建哪些对象,比如在 Web API 服务中。在下面的 RegisterServices ,我告诉 Ninject 分配客户数据服务和产品数据服务到他们各自实现的接口中。这就告诉了 Ninject 去哪儿加载匹配的 dll 引用。


using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Web.Http;

using CodeProject.Portal.Models;

using CodeProject.Business.Entities;

using CodeProject.Business;

using CodeProject.Interfaces;

using Ninject;


namespace CodeProject.Portal.WebApiControllers

{

    [RoutePrefix("api/CustomerService")]

    public class CustomerServiceController : ApiController

    {


        [Inject]

        public ICustomerDataService _customerDataService { get; set; }


        /// <summary>

        /// Create Customer

        /// </summary>

        /// <param name="request"></param>

        /// <param name="customerViewModel"></param>

        /// <returns></returns>

        [Route("CreateCustomer")]     

        [HttpPost]

        public HttpResponseMessage CreateCustomer(HttpRequestMessage request, 

                                   [FromBody] CustomerViewModel customerViewModel)

        {

            TransactionalInformation transaction;


            Customer customer = new Customer();

            customer.CompanyName = customerViewModel.CompanyName;

            customer.ContactName = customerViewModel.ContactName;

            customer.ContactTitle = customerViewModel.ContactTitle;

            customer.CustomerCode = customerViewModel.CustomerCode;

            customer.Address = customerViewModel.Address;

            customer.City = customerViewModel.City;

            customer.Region = customerViewModel.Region;

            customer.PostalCode = customerViewModel.PostalCode;

            customer.Country = customerViewModel.Country;

            customer.PhoneNumber = customerViewModel.PhoneNumber;

            customer.MobileNumber = customerViewModel.MobileNumber;


            CustomerBusinessService customerBusinessService = 

                                    new CustomerBusinessService(_customerDataService);


            customerBusinessService.CreateCustomer(customer, out transaction);

            if (transaction.ReturnStatus == false)

            {                

                customerViewModel.ReturnStatus = false;

                customerViewModel.ReturnMessage = transaction.ReturnMessage;

                customerViewModel.ValidationErrors = transaction.ValidationErrors;


                var responseError = Request.CreateResponse<CustomerViewModel>

                                    (HttpStatusCode.BadRequest, customerViewModel);

                return responseError;

              

            }


            customerViewModel.CustomerID = customer.CustomerID;

            customerViewModel.ReturnStatus = true;

            customerViewModel.ReturnMessage = transaction.ReturnMessage;


            var response = Request.CreateResponse<CustomerViewModel>

                           (HttpStatusCode.OK, customerViewModel);

            return response;


        }

使用 Ninject 数据注解[注入],你可以告诉 Ninject 库何时何地实例化你的对象。在下面的网页 API 服务,客户数据服务就是由 Ninject 创建的。由于客户业务服务依赖于客户数据的服务来访问数据,客户数据服务应该被注入客户业务服务的构造函数中。所有这一切都是通过创建客户数据的服务接口,然后简单地实现了客户数据服务接口来完成的。依赖注入是功能强大的,因为它创造应用代码彼此分离的耦合度低的应用层。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Web.Http;

using CodeProject.Portal.Models;

using CodeProject.Business.Entities;

using CodeProject.Business;

using CodeProject.Interfaces;

using Ninject;


namespace CodeProject.Portal.WebApiControllers

{

    [RoutePrefix("api/CustomerService")]

    public class CustomerServiceController : ApiController

    {


        [Inject]

        public ICustomerDataService _customerDataService { get; set; }


        /// <summary>

        /// Create Customer

        /// </summary>

        /// <param name="request"></param>

        /// <param name="customerViewModel"></param>

        /// <returns></returns>

        [Route("CreateCustomer")]     

        [HttpPost]

        public HttpResponseMessage CreateCustomer(HttpRequestMessage request, 

                                   [FromBody] CustomerViewModel customerViewModel)

        {

            TransactionalInformation transaction;


            Customer customer = new Customer();

            customer.CompanyName = customerViewModel.CompanyName;

            customer.ContactName = customerViewModel.ContactName;

            customer.ContactTitle = customerViewModel.ContactTitle;

            customer.CustomerCode = customerViewModel.CustomerCode;

            customer.Address = customerViewModel.Address;

            customer.City = customerViewModel.City;

            customer.Region = customerViewModel.Region;

            customer.PostalCode = customerViewModel.PostalCode;

            customer.Country = customerViewModel.Country;

            customer.PhoneNumber = customerViewModel.PhoneNumber;

            customer.MobileNumber = customerViewModel.MobileNumber;


            CustomerBusinessService customerBusinessService = 

                                    new CustomerBusinessService(_customerDataService);


            customerBusinessService.CreateCustomer(customer, out transaction);

            if (transaction.ReturnStatus == false)

            {                

                customerViewModel.ReturnStatus = false;

                customerViewModel.ReturnMessage = transaction.ReturnMessage;

                customerViewModel.ValidationErrors = transaction.ValidationErrors;


                var responseError = Request.CreateResponse<CustomerViewModel>

                                    (HttpStatusCode.BadRequest, customerViewModel);

                return responseError;

              

            }


            customerViewModel.CustomerID = customer.CustomerID;

            customerViewModel.ReturnStatus = true;

            customerViewModel.ReturnMessage = transaction.ReturnMessage;


            var response = Request.CreateResponse<CustomerViewModel>

                           (HttpStatusCode.OK, customerViewModel);

            return response;


        }

结论

在 ASP.NET MVC 和 ASP.NET 捆绑中集成 AngularJS 似乎是一个开始时看起来像挑战的尝试。在试验和失败的每次迭代中,这个挑战变得逐渐变得不那么难。我只是想使所有这些集成起来工作,我不会停止努力。

你可以争论在 ASP.NET 中使用捆绑和缩功能和在 Grunt 与 Gulp 部分使用流行的压缩工具,其各自的优点。如果你是一个无需学习另外技术和工具并且喜欢点击按钮来发布你的 Visual Studio 的微软开发人员,你很可能会想使用 ASP.NET 捆绑功能。我发现这个功能确实是我想要的,它只是花费了我很长的时间来弄清楚如何将它与 AngularJS 集成。

在这些天里,有很多技术可以来写。我以后的一些文章中可能包括 AngularJS 2 和 MEAN 的其余部分,包括 Node.js 的,Express 和 MongoDB。

还有一些包含在最新发布的 Visual Studio 2015 中的一些使用 Apache Cordov 开发的移动应用。这种先进的 HTML 混合的移动应用框架很可能可以和 Apache Cordov 一起工作使用。据说 Ionic 能够使用 HTML 和 AngularJS ,并且可以很容易的建立大规模交互式的移动应用。敬请期待! 

文章来源:By Mark J. Caplin 

原文链接:http://www.codeproject.com/Articles/1033076/Integrating-AngularJS-with-ASP-NET-MVC


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328541.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小菜:关于main方法的面试题

转载自 小菜&#xff1a;关于main方法的面试题问题&#xff1a;如果main方法被声明为private会怎样&#xff1f; 答案&#xff1a;能正常编译&#xff0c;但运行的时候会提示“main方法不是public的”。问题&#xff1a;如果去掉了main方法的static修饰符会怎样&#xff1f; 答…

kali linux改中文_kali linux 2019.4设置为中文方法

就在前天&#xff0c;2019年11月26日&#xff0c;kali Linux官网发布了最新版本&#xff1a;Kali Linux 2019.4发行版&#xff0c;此版本和之前相比变动很大&#xff0c;系统界面、主题、壁纸都灿然一新。Kali Linux2019.4版本包括了一些令人兴奋的新更新:一个新的默认桌面环境…

构建高可用ZooKeeper集群

ZooKeeper 是 Apache 的一个顶级项目&#xff0c;为分布式应用提供高效、高可用的分布式协调服务&#xff0c;提供了诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知和分布式锁等分布式基础服务。由于 ZooKeeper 便捷的使用方式、卓越的性能和良好的稳定性&#xff0c…

面试官角度弹面试

http://www.iteye.com/topic/715304 这个帖子的背景是今晚看到je上这张贴&#xff1a;http://www.iteye.com/topic/715256&#xff0c;心血来潮写下的文字&#xff0c;如果能抛砖引玉&#xff0c;能有其他面试官分析一下自己面试时问的问题&#xff0c;那或许是件很有意义的事…

面试经历—广州YY(欢聚时代)

转载自 面试经历—广州YY&#xff08;欢聚时代&#xff09; 上周去YY&#xff08;欢聚时代&#xff09;面试JAVA工程师&#xff0c;现在回忆一下当时的面试过程&#xff0c;面试问的问题有&#xff1a;1、常用的集合类HashMap、HashTable、ArrayList、LinkedList、HashSet2、…

mysql binlog 备份恢复数据_Mysql结合备份+binlog恢复误删除操作数据

结合备份binlog恢复数据。场景&#xff1a;昨天晚上做了全备&#xff0c;今天上午用户不小心误删除某张表。解决方案&#xff1a;不建议在原生产环境直接恢复&#xff0c;建议在另一台机器恢复全库日志&#xff0c;然后导入到生产环境。1) 创建表select now();create table itp…

你们也只剩下点赞的交情

作者|北及企鹅 微信|叁禁 01 你们有没有这样的朋友&#xff0c;他们在你的世界里扮演着退化的角色。 也许友谊的开始只是小学一年级的时候他对你说了一声“我也喜欢看小丸子。”你们就手拉手肩并肩当了很久的密友。 也许是因为初中那次你俩都没交作业一起在楼道罚站&#xff0…

IBM® Bluemix 上运行ASP.NET Core

IBM Bluemix 上的“ASP.NET 核心”运行时采用“ASP.NET 核心”buildpack 技术。“ASP.NET 核心”是用于构建 .NET Web 应用程序的模块化开放式源代码框架。“.Net 核心”是跨平台的小型运行时&#xff0c;可由“ASP.NET 核心”应用程序实现。将它们相结合可实现基于云的先进 We…

拦截器 和过滤器

https://blog.csdn.net/zxd1435513775/article/details/80556034 拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;的执行顺序和区别 2018年06月03日 13:31:00 止步前行 阅读数&#xff1a;2871 标签&#xff1a; FilterInterceptorControll…

解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别

转载自 解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别 标准Http协议支持六种请求方法&#xff0c;即&#xff1a; 1、GET 2、POST 3、PUT 4、Delete 5、HEAD 6、Options 但其实我们大部分情况下只用到了GET和POST。如果想设计一个符合RESTful规范的web…

攻城掠地端mysql_【图片】攻城掠地单机版本服务端+攻城掠地GM工具【单兆权吧】_百度贴吧...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼player_wepon 兵器 宝石修改&#xff0e;1&#xff0c;为1级宝石  1001&#xff0c;1级晶石修改最好手动修改&#xff0c;手自进阶  最多改六个一多出错player_tickets  点卷改修activity    活动表store_house  背包表p…

同步和异步有何异同,什么场景使用

同步和异步有何异同&#xff0c;什么场景使用&#xff0c;举例说明&#xff01; 2016年11月30日 18:47:26 qq_36179561 阅读数&#xff1a;1752更多 个人分类&#xff1a; 基础知识 同步:发送一个请求,等待返回,然后再发送下一个请求 异步:发送一个请求,不等待返回,随时可以…

面试经历---YY欢聚时代

转载自 面试经历---YY欢聚时代&#xff08;2015年11月21日上午初试、25日下午复试&#xff09;YY欢聚时代一年多前去面试过一次&#xff0c;当时鄙视了&#xff0c;在现在的公司呆了1年半了&#xff0c;感觉做得很不爽&#xff0c;而且薪资又不满意&#xff0c;所以想找个新工…

走进异步编程的世界 - 开始接触 async/await

序 这是学习异步编程的入门篇。 涉及 C# 5.0 引入的 async/await&#xff0c;但在控制台输出示例时经常会采用 C# 6.0 的 $"" 来拼接字符串&#xff0c;相当于string.Format() 方法。 目录 Whats 异步&#xff1f;async/await 结构What’s 异步方法&#xff1f; 一、…

所有的软弱,都是昂贵的

作者&#xff1a;周冲 来源&#xff1a;周冲的影像声色&#xff08;fuck_your_dick&#xff09; 01 契诃夫有一个小说&#xff0c;名叫《柔弱的人》&#xff0c;讲一个主人&#xff0c;巧立名目&#xff0c;剥夺家庭教师的工资。 首先&#xff0c;他压缩掉她的周末&#xff0c…

python3中urlopen_解决python3 urllib中urlopen报错的问题

前言最近更新了Python版本&#xff0c;准备写个爬虫&#xff0c;意外的发现urllib库中属性不存在urlopen&#xff0c;于是各种google&#xff0c;然后总结一下给出解决方案问题的出现AttributeError: module object has no attribute urlopen问题的解决途径我们先来看下官方文档…

100+经典Java面试题及答案解析

转载自 100经典Java面试题及答案解析面向对象编程&#xff08;OOP&#xff09;Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点&#xff1a; 代码开发模块化&#xff0c;更易维护和修改。代码复用。增强代码的可靠性和灵活性。增加代…

.NET HttpClient的缺陷和文档错误让开发人员倍感沮丧

设计错误、缺陷及文档错误等导致正确使用.NET HttpClient变得出奇地困难。所以&#xff0c;即使是生产环境中看似运行正常的应用程序&#xff0c;在负荷不满的情况下&#xff0c;也遭受着性能问题和运行时故障。 来自ASP.NET Monsters的Simon Timms就通过一篇题为“你正在错误地…

python监听剪贴板_Python监听剪切板实现方法代码实例

第一种import win32clipboardimport time#速度快 容易出错class niubi():def lihai(self):while True:#jianting().main()t jianting().main()print(t)class jianting():def clipboard_get(self):"""获取剪贴板数据"""win32clipboard.OpenClipb…

新闻发布项目——业务逻辑层(UserService)

package bdqn.newsManageServlet.Service;import bdqn.newsManageServlet.entity.User;/*** 用户信息* author Administrator**/ public interface UserService {public User getLoginUser(String uName,String pwd, String msg);}