对一个前端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 = {};
            });
        }
    });
时间: 2024-10-06 07:19:32

对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解的相关文章

对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(4)

chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angularjs文章:http://chsakell.com/2015/08/23/building-single-page-applications-using-web-api-and-angularjs-free-e-book/ 这里记录下对此项目的理解.分为如下几篇: ● 对一个前端使用AngularJ

对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(3)

chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angularjs文章:http://chsakell.com/2015/08/23/building-single-page-applications-using-web-api-and-angularjs-free-e-book/ 这里记录下对此项目的理解.分为如下几篇: ● 对一个前端使用AngularJ

对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(1)

chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angularjs文章:http://chsakell.com/2015/08/23/building-single-page-applications-using-web-api-and-angularjs-free-e-book/ 这里记录下对此项目的理解.分为如下几篇: ● 对一个前端使用AngularJ

对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(2)

chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angularjs文章:http://chsakell.com/2015/08/23/building-single-page-applications-using-web-api-and-angularjs-free-e-book/ 这里记录下对此项目的理解.分为如下几篇: ● 对一个前端使用AngularJ

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-en

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-enable-session-

前端使用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 cla

通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用

REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站,企业级Web应用对用户体验的要求要低一些.不过客户对“用户体验”的要求是“与日俱增”的,很多被“惯坏了”的用户已经不能忍受Postback带来的页面刷新,所以Ajax在企业级Web应用中得到了广泛的应用.企业级Web应用的一个特点是以“数据处理”为主,所以“面向绑定”的Knockout.js 是一