你的位置:首页 > ASP.net教程

[ASP.net教程]对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解


 

依然chsakell,他写了一篇前端AngularJS,后端OData,ASP.NET Web API的Demo,关于OData在ASP.NET Web API中的正删改查没有什么特别之处,但在前端调用API时,把各种调用使用$resouce封装在一个服务中的写法颇有借鉴意义。

 

文章:http://chsakell.com/2015/04/04/asp-net-web-api-feat-odata/
源码:https://github.com/chsakell/odatawebapi

 

首先是领域模型。

 

public class Employee{  public int ID{get;set;}    ...  public int AddressID { get; set; }  public virtual Address Address { get; set; }  public int CompanyID { get; set; }  public virtual Company Company { get; set; }}public class Address{  public int ID{get;set;}  ...}public class Company{  public int ID{get;set;}    ..  public virtual List<Employee> Employees{get;set;}    public Compay()  {    Employees = new List<Employee>();  }}

 

使用EF Fuent API对领域进行配置,继承EntityTypeConfiguration<T>,比如:

 

public class CompanyConfiguration: EntityTypeConfiguration<Company>{}

 

上下文继承DbContext。

 

public class EntitiesContext : DbContext{}

 

种子数据继承DropCreateDatabaseIfModelChanges.

 

public class EntitiesInitializer : DropCreateDatabaseIfModelChanges<EntitiesContext>{}

 

配置项目连接字符串。

 

<connectionStrings> <add name="EntitiesContext" providerName="System.Data.SqlClient" connectionString="Server=(localdb)\v11.0; Database=CompanyDB; Trusted_Connection=true; MultipleActiveResultSets=true" /></connectionStrings>

 

在项目全局文件中启用种子数据的配置。

 

protected void Application_Start(){  GlobalConfiguration.Configure(WebApiConfig.Register);  // Init the database  Database.SetInitializer(new EntitiesInitializer());}

 

在NuGet中输入odata,安装V4.0版本。

 

关于ODataController的增删改查,在"ASP.NET Web API基于OData的增删改查,以及处理实体间关系"比较详细的描述,这里略去,把重点放在前端的调用上。

 

先来看界面:

 

 

这里有个主视图,如下:

 

<html ng-app="mainApp">  <head>    <link href="Content/styles/toastr.css" rel="stylesheet" />    <link href="Content/styles/loading-bar.css" rel="stylesheet" />        <script src="Content/scripts/jquery-2.1.1.js"></script>    <script src="Content/scripts/bootstrap.js"></script>    <script src="Content/scripts/angular.js"></script>    <script src="Content/scripts/angular-resource.js"></script>    <script src="Content/scripts/toastr.js"></script>    <script src="Content/scripts/loading-bar.js"></script>    <script src="Content/scripts/main.js"></script>    <script src="app/services.js"></script>    <script src="app/controllers.js"></script>  </head>  <body ng-controller="appCtrl" ng-init="getTop10Employees()">     <tbody ng-repeat="emp in employees">      <tr ng-click="setEmployee(emp)">        <td>{{emp.ID}}</td>        <td>{{emp.FirstName}}</td>        <td>{{emp.Surname}}</td>        <td>{{emp.Email}}</td>      </tr>    </tbody>          <!--更新或删除-->    <form>      <input type="text" id="id" ng-model="currentEmployee.ID" disabled>      <input type="text" id="firstName" ng-model="currentEmployee.FirstName">      <input type="text"id="surname" ng-model="currentEmployee.Surname">      <input type="email" id="inputEmail" ng-model="currentEmployee.Email">      <input type="text" id="city" ng-model="currentEmployee.City" disabled>      <input type="text" id="country" ng-model="currentEmployee.Country" disabled>      <input type="text" id="state" ng-model="currentEmployee.State" disabled>      <input type="text" id="company" ng-model="currentEmployee.Company" disabled>      <button type="button" ng-click="updateEmployee()">Update</button>      <button type="button" ng-click="deleteEmployee()">Delete</button>    </form>        <!--添加-->    <form role="form">      <input type="text" name="firstname" ng-model="newEmployee.FirstName" />      <input type="text" name="surname" ng-model="newEmployee.Surname" />      <input type="text" name="email" ng-model="newEmployee.Email" />      <button type="button" ng-click="addEmployee()">Add</button>    </form>         <script type="text/javascript">      $(function () {        toastr.options = {          "positionClass": "toast-bottom-right",          "preventDuplicates": true,          "progressBar": true,          "timeOut": "3000",        }      });    </script>         </body></html>

 

一般来说,前端针对某个领域的操作有多个,chsakell的一种写法特别值得推荐,那就是把针对某个领域的操作,在AngularJS中,用$resource封装到一个服务中去。如下:

 

angular.module('mainApp')  .factory('employeeService', function ($resource) {    var odataUrl = '/odata/Employees';    return $resource('', {},      {        'getAll': { method: 'GET', url: odataUrl },        'getTop10': { method: 'GET', url: odataUrl + '?$top=10' },        'create': { method: 'POST', url: odataUrl },        'patch': { method: 'PATCH', params: { key: '@key' }, url: odataUrl + '(:key)' },        'getEmployee': { method: 'GET', params: { key: '@key' }, url: odataUrl + '(:key)' },        'getEmployeeAdderss': { method: 'GET', params: { key: '@key' }, url: odataUrl + '(:key)' + '/Address' },        'getEmployeeCompany': { method: 'GET', params: { key: '@key' }, url: odataUrl + '(:key)' + '/Company' },        'deleteEmployee': { method: 'DELETE', params: { key: '@key' }, url: odataUrl + '(:key)' },        'addEmployee': { method: 'POST', url: odataUrl }      });  }).factory('notificationFactory', function () {    return {      success: function (text) {        toastr.success(text, "Success");      },      error: function (text) {        toastr.error(text, "Error");      }    };  })

 

然后针对Employee,在mainApp中增减一个controller用来针对Employee的各种操作。

 

angular.module('mainApp')  .controller('appCtrl', function ($scope, employeeService, notificationFactory) {    //存储当前用户    $scope.currentEmployee = {};    // Get Top 10 Employees    $scope.getTop10Employees = function () {      (new employeeService()).$getTop10()        .then(function (data) {                    //存储所有用户          $scope.employees = data.value;          $scope.currentEmployee = $scope.employees[0];                    //相当于设置Empoyee的导航属性          $scope.setCurrentEmployeeAddress();          $scope.setCurrentEmployeeCompany();                    //通知          notificationFactory.success('Employeess loaded.');        });    };    // Set active employee for patch update    $scope.setEmployee = function (employee) {      $scope.currentEmployee = employee;      $scope.setCurrentEmployeeAddress();      $scope.setCurrentEmployeeCompany();    };    //设置当前Employee的地址    $scope.setCurrentEmployeeAddress = function () {      //获取当前Employee      var currentEmployee = $scope.currentEmployee;      return (new employeeService({        "ID": currentEmployee.ID,      })).$getEmployeeAdderss({ key: currentEmployee.ID })      .then(function (data) {        $scope.currentEmployee.City = data.City;        $scope.currentEmployee.Country = data.Country;        $scope.currentEmployee.State = data.State;      });    }    //设置当前Employee的Company    $scope.setCurrentEmployeeCompany = function () {      var currentEmployee = $scope.currentEmployee;      return (new employeeService({        "ID": currentEmployee.ID,      })).$getEmployeeCompany({ key: currentEmployee.ID })      .then(function (data) {        $scope.currentEmployee.Company = data.Name;      });    }    // Update Selected Employee    $scope.updateEmployee = function () {      var currentEmployee = $scope.currentEmployee;      console.log(currentEmployee.Email);      if (currentEmployee) {        return (new employeeService({          "ID": currentEmployee.ID,          "FirstName": currentEmployee.FirstName,          "Surname": currentEmployee.Surname,          "Email": currentEmployee.Email        })).$patch({ key: currentEmployee.ID })        .then(function (data) {          notificationFactory.success('Employee with ID ' + currentEmployee.ID + ' updated.')        });      }    }    $scope.deleteEmployee = function () {      var currentEmployee = $scope.currentEmployee;      return (new employeeService({        "ID": currentEmployee.ID,      })).$deleteEmployee({ key: currentEmployee.ID })      .then(function (data) {        notificationFactory.success('Employee with ID ' + currentEmployee.ID + ' removed.');        $scope.getTop10Employees();      });    }    $scope.addEmployee = function () {      var newEmployee = $scope.newEmployee;      return (new employeeService({        "FirstName": newEmployee.FirstName,        "Surname": newEmployee.Surname,        "Email": newEmployee.Email,        "AddressID": 1, // normally obtained from UI        "CompanyID": 3 // normally obtained from UI      })).$addEmployee()      .then(function (data) {        notificationFactory.success('Employee ' + newEmployee.FirstName + ' ' + newEmployee.Surname          + ' added successfully');                $scope.newEmployee = {};      });    }  });