前端使用AngularJS的$resource,后端ASP.NET Web API,實現增刪改查


 

AngularJS中的$resource服務相比$http服務更適合與RESTful服務進行交互。本篇后端使用ASP.NET Web API, 前端使用$resource,實現增刪改查。

 

本系列包括:

1、前端使用AngularJS的$resource,后端ASP.NET Web API,實現增刪改查
2、前端使用AngularJS的$resource,后端ASP.NET Web API,實現分頁、過濾

 

領域和上下文

 

首先領域先行。

 

    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>

 

 待續~~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM