zoukankan      html  css  js  c++  java
  • 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查

    首页 > 技术 > 编程 > NET > 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查
     

    前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查


    AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互。本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查。

    领域和上下文

    首先领域先行。

        public class StudentVm
        {
            [Key]
            public int Id { get; set; }
            public string Name { get; set; }
            public string Age { get; set; }
        }

    上下文。

            public class StudentContext : DbContext
            {
                public StudentContext() : base("conn")
                {
                    Database.SetInitializer(new StudentInitializer());
                }
    
                public DbSet<StudentVm> Students { get; set; }
            }

    上下文的构造函数中,StudentIntializer类对数据进行了初始化。

        public class StudentInitializer : CreateDatabaseIfNotExists<StudentContext>
        {
            protected override void Seed(StudentContext context)
            {
                IList<StudentVm> students = new List<StudentVm>();
                students.Add(new StudentVm() { Name = "aa", Age = "20" });
                students.Add(new StudentVm() { Name = "bb", Age = "18" });
                students.Add(new StudentVm() { Name = "cc", Age = "22" });
                students.Add(new StudentVm() { Name = "dd", Age = "23" });
                students.Add(new StudentVm() { Name = "ee", Age = "20" });
                students.Add(new StudentVm() { Name = "ff", Age = "21" });
                students.Add(new StudentVm() { Name = "gg", Age = "28" });
    
                foreach(StudentVm student in students)
                {
                    context.Students.Add(student);
                }
    
                base.Seed(context);
            }
        }

    对于EF Code First来说,Web.config中需要配置连接字符串。

      <connectionStrings>
        <add name="conn"
           connectionString="Data Source=.;User=yourname;Password=yourpassword;Initial Catalog=StudentsDemo;Integrated Security=True"
           providerName="System.Data.SqlClient"/>
      </connectionStrings>

    Repository


    在这里使用上下文类,实现增删改查。

        public class StudentsReop
        {
            private StudentContext _db = new StudentContext();
    
            public IEnumerable<StudentVm> Query()
            {
                return _db.Students;
            }
    
            public StudentVm Get(int id)
            {
                return _db.Students.SingleOrDefault(s => s.Id == id);
            }
    
            //更新
            public void Put(int id, StudentVm student)
            {
                var stu = _db.Students.SingleOrDefault(s => s.Id == id);
                _db.Students.Attach(stu);
                _db.Entry(stu).State = System.Data.Entity.EntityState.Modified;
                _db.Entry(stu).CurrentValues.SetValues(student);
                _db.SaveChanges();
            }
    
            //添加
            public void Post(StudentVm student)
            {
                _db.Students.Add(student);
                _db.SaveChanges();
            }
    
            public void Delete(int id)
            {
                var student = _db.Students.SingleOrDefault(s => s.Id.Equals(id));
                _db.Students.Remove(student);
                bool saveFailed;
                do
                {
                    saveFailed = false;
    
                    try
                    {
                        _db.SaveChanges();
                    }
                    catch (DbUpdateConcurrencyException ex)
                    {
                        saveFailed = true;
    
                        //重新加载数据库中的实体,使之处于unchanged的状态
                        ex.Entries.Single().Reload();
                    }
                } while (saveFailed);
            }
        }

    API控制器

       public class StudentsController : ApiController
        {
            private StudentsReop _reop = new StudentsReop();
    
            //GET api/Students
            public HttpResponseMessage Get()
            {
                var students = _reop.Query().ToList();
                return Request.CreateResponse(HttpStatusCode.OK, students);
            }
    
            //GET api/Students/5
            public HttpResponseMessage Get(int id)
            {
                var student = _reop.Get(id);
                return Request.CreateResponse(HttpStatusCode.OK, student);
            }
    
    
            //POST api/Students
            public void Post([FromBody]StudentVm student)
            {
                _reop.Post(student);
            }
    
    
            //PUT api/Students/5
            public void Put(int id, [FromBody]StudentVm student)
            {
                _reop.Put(id, student);
            }
    
    
            //DELETE api/Students
            public void Delete(int id)
            {
                _reop.Delete(id);
            }
        }

    允许跨域访问

    默认情况下,ASP.NET Web API是不支持跨域访问的。为了支持,需要安装Microsoft.AspNet.WebApi.Cors。安装之后,需要在全局配置生效。在WepApiConfig.cs中配置如下:

        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API 配置和服务
    
                // Web API 路由
                config.MapHttpAttributeRoutes();
    
                config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }

    在本地,浏览器中:http://localhost:49621/api/Students

    前端准备

    后端完成,前端在WebStorm下安装先安装需要的几个插件:


    npm install angular
    npm install angular-route
    npm install angular-resource
    npm install angular-cookies
    npm install alertify


    再来了解下前端的文件结构:

    app.js 主module,路由都在这里配置
    index.html 主视图,引用所有的css,js文件,提供让其它部分视图呈现的一块区域<div ng-view></div>
    .....service/ 自定义服务,$resouce的核心就封装在这里
    ..........studentService.js
    .....controller/
    ..........studentsCtrl.js 列表
    ..........studentUpdateCtrl.js 更新
    ..........studentCreateCtrl.js 添加
    .....views/
    ..........Students.html 列表
    ..........StudentInfo.html 更新
    ..........StudentCreate.html 添加


    index.html

    
    
    
    <!DOCTYPE html>
    <html lang="en" ng-app="studentManagement">
    <head>
      <meta charset="UTF-8">
      <title>{{title}}</title>
      <link rel="stylesheet" href="node_modules/alertify/themes/alertify.core.css"/>
    </head>
    <body>
      <div>
        <p>
          <a href="#/">Students</a>
          &nbsp;&nbsp;
          <a href="#/Create">Create Student</a>
        </p>
      </div>
    
      <div ng-view></div>
    
      <script src="node_modules/angular/angular.min.js"></script>
      <script src="node_modules/angular-route/angular-route.min.js"></script>
      <script src="node_modules/angular-resource/angular-resource.min.js"></script>
      <script src="node_modules/angular-cookies/angular-cookies.min.js"></script>
      <script src="node_modules/alertify/lib/alertify.min.js"></script>
    
      <script src="app.js"></script>
    
      <script src="service/studentService.js"></script>
      <script src="controller/studentUpdateCtrl.js"></script>
      <script src="controller/studentsCtrl.js"></script>
      <script src="controller/studentCreateCtrl.js"></script>
    
    </body>
    </html>

    以上,主视图中,需要注意引用js文件的顺序,一般angualr相关方在最上面,然后app对应js文件,最后是各种服务和控制器相关js文件。

    app.js

    在这里,当然首先要定义一个module,定义module的时候要把所有用到的module依赖写在module方法的第二个实参里。还有一个主项工作就是定义设置路由,而且,如果想让以后视同从controller中拿数据更快,我们还可以利用路由的resolve机制,把数据从某处读取出来,先放到路由中,然后在controller中把resolve机制下的数据读出来。

    "use strict";
    
    var studentsManagement = angular.module("studentManagement",["ngResource","ngCookies","ngRoute"])
        .run(function($rootScope){
            $rootScope.title = "Home";
        })
        .config(["$routeProvider","$locationProvider", function($routeProvider, $locationProvider){
    
            //关于url的基本配置
            //$locationProvider.html5Mode({
            //    enabled: true,
            //    requireBase: false
            //});
    
            //配置路由
            $routeProvider.when("/", {
                templateUrl: "views/Students.html",
                controller: "studentsCtrl",
                resolve: {
                    students: function($q,studentDataService){
    
                        //$q异步执行方法
                        var deferred = $q.defer();
                        studentDataService.query(function(data){
                            deferred.resolve(data);
                        });
    
                        return deferred.promise;
                    }
                }
            }).when("/Student/:id",{
                templateUrl: "views/StudentInfo.html",
                controller: "studentUpdateCtrl",
                resolve: {
                    student: function($q, studentDataService, $route){
                        var defered = $q.defer();
    
                        //从路由中获取id的值
                        var id = $route.current.params.id;
    
                        studentDataService.get({id: id}, function(data){
                            defered.resolve(data);
                        });
    
                        return defered.promise;
                    }
                }
            }).when("/Create",{
                templateUrl: "views/CreateStudent.html",
                controller: "studentCreateCtrl"
            });
    
        }]);

    ● 使用$routeProvider配置路由的过程就是让一对对view和controller结婚的过程

    ● 显示列表的时候通过路由的resolve机制把数据先放在了路由中

    ● 显示某个Sudent的时候也通过路由的resolve机制把数据先放在了路由中

    ●/Student/:id这个路由格式中的id代表变量,可借助$route服务从路由中取出来var id = $route.current.params.id;

    studentService.js

    在这里,封装了对API的所有请求。

    而$resource服务是位于angular-resource中,大致按如下调用:

    $resource(url,{paramDefaults},{actions},{options});

    其中,第一个参数是必须的,其它都optional。

    angular.module('studentManagement').factory("studentDataService",["$resource", function($resource){
    
        var baseUrl = "http://localhost:49621/api/Students";
        return $resource("http://localhost:49621/api/Students",{},{
            query: {method: "GET", isArray: true },
            create: {method: "POST"},
            get: {method: "GET", url: baseUrl + "?id=:id"},
            remove: {method: "DELETE", url: baseUrl + "?id=:id"},
            update: {method: "PUT", url: baseUrl + "?id=:id"}
        })
    }]);

    以上,在"?id=:id"中,冒号后面的id是一个变量,在controller中通过对象传递到这里来,比如studentDataService.remove({id: id}).$promise.then(...)

    列表,studentsCtr.j和views/Students.html这对恋人

    studentsCtr.js:

    angular.module('studentManagement').controller("studentsCtrl",['$scope','$route','$rootScope','studentDataService', function($scope,$route, $rootScope, studentDataService){
        $rootScope.title = "Students";
        $scope.students = $route.current.locals.students;//students在路由resolve中定义
        $scope.removeStudent = function(id, student){
            studentDataService.remove({id: id}).$promise.then(function(){
                //获取student在当前集合中的索引
                var index = $scope.students.indexOf(student);
                $scope.students.splice(index, 1);
                alertify.log(student.Name + ' is removed');
            });
        };
    
    }]);

    以上,students的数据并没有向那个源头发出请求获取,而是直接使用$route服务,把路由resolve机制中的变量值取了出来。删除数据实际是做2件事,一件是删除服务端的数据,一件是删除model中的数据。

    Students.html:

    <table>
      <thead>
        <tr>
          <th>Name</th><th>Age</th><th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="student in students">
          <td>{{student.Name}}</td>
          <td>{{student.Age}}</td>
          <td>
            <a href="#/Student/{{student.Id}}">更新</a>
            &nbsp;&nbsp;
            <a href="javascript:void(0)" ng-click="$parent.removeStudent(student.Id, student)">移除</a>
          </td>
        </tr>
      </tbody>
    </table>

    添加,studentCreateCtrl.js和views/CreateStudent.html这对恋人

    studentCreateCtrl.js:

    angular.module('studentManagement').controller("studentCreateCtrl", ["$scope", "studentDataService", '$rootScope', "$location", function ($scope, studentDataService, $rootScope, $location) {
        $rootScope.title = "Create student";
    
        $scope.saveStudent = function (student) {
            studentDataService.create(student).$promise.then(function (res) {
                $location.path('/');
            });
        };
    }]);

    CreateStudent.html:

    <form>
      <input id="userName" ng-model="student.Name" />
      <br/>
      <input id="userAge" ng-model="student.Age" />
      <br/>
      <button ng-click="saveStudent(student)">Save</button>
      <button type="reset">Cancel</button>
    </form>

    更新,studentUpdateCtrl.js和views/StudentInfo.html这对恋人

    studentUpdateCtrl.js:

    angular.module('studentManagement').controller("studentUpdateCtrl",["$scope","$route","$rootScope","studentDataService","$location", function($scope,$route, $rootScope, studentDataService, $location){
    
        //student是在resolve中定义的
        $scope.student = $route.current.locals.student;
        $rootScope.title = "Student Info -" + $scope.student.Name;
        $scope.updateInfo = function(student){
          studentDataService.update({id: student.Id}, student).$promise.then(function(){
              $location.url("/");
              alertify.log("Updated Student Scucess");
          });
        };
    }]);

    StudentInfo.html:

    <form>
      <input type="text" id="userName" ng-model="student.Name"/>
      <br/>
      <input type="text" id="userAge" ng-model="student.Age"/>
      <br/>
      <button ng-click="updateInfo(student)">Update</button>
      <button type="reset">Reset</button>
    </form>
  • 相关阅读:
    java编程规范
    Servlet生命周期
    BBS
    Hibernate主键自增策略
    MyBatis举例以及连接数据库过程
    myBatis框架的配置部分
    持续集成
    2017-02-23 .NET Core Tools转向使用MSBuild项目格式
    记录表TABLE中 INDEX BY BINARY_INTEGER 的作用
    什么是 BIND 变量?
  • 原文地址:https://www.cnblogs.com/zxtceq/p/6394610.html
Copyright © 2011-2022 走看看