• 对一个前端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 = {};
                });
            }
        });
  • 相关阅读:
    如何用redis/memcache做Mysql缓存层?
    孤儿进程和僵尸进程总结
    二叉树的遍历(非递归)
    Linux进程分配内存的两种方式--brk() 和mmap()
    Hbase
    cgroup 分析之CPU和内存部分
    十道海量数据处理面试题与十个方法大总结
    快速定位性能瓶颈,检查出所有资源(CPU、内存、磁盘IO等)的利用率(utilization)、饱和度(saturation)和错误(error)度量,即USE方法
    红黑树
    tcp 两个重要窗口:滑动窗口 和 拥塞窗口
  • 原文地址:https://www.cnblogs.com/darrenji/p/4960522.html
Copyright © 2020-2023  润新知