依然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 = {};
});
}
});

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

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

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

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

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

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

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

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

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP. ...

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车 ...

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

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

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

    REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站 ...

随机推荐

  1. 五大常见的MySQL高可用方案【转】

    1. 概述 我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中 ...

  2. MVC 控制器中传递dynamic(对象) 给视图

    有时候不想重新定义一个实体,则使用 dynamic 来定义匿名类型. //匿名类型 传递到前台 Model dynamic viewModel = new { UserID = 5016 }; ret ...

  3. 为你详细解读HTTP请求头的具体含意

    当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头的内容生成当次请求的内容发送给浏览器.你明白HTTP请求头的具体含意吗?下面一条条的为你详细解读,先看 ...

  4. 文字小于12px时,设置line-height不居中问题

    设置了文字了小于12px时,会存在设置了line-height的不生效的问题,主要是由于基线的问题,这篇文章解释的很清楚,有兴趣的可以看下https://blog.csdn.net/q12151634 ...

  5. 批量初始化数组和memset函数

    对于数组的初始化有一下三种方式: int  a[]={1,2,3,4,5} //通过判断初始化值得个数来却仍数组长度 int b[5]={1,2,3} //数组长度为5,可是初始值却只有三个,因此,不 ...

  6. 2018ACM/ICPC 青岛现场赛 E题 Plants vs. Zombies

    题意: 你的房子在0点,1,2,3,...,n(n<=1e5)点每个点都有一颗高度为0的花,浇一次水花会长a[i]. 你有一个机器人刚开始在你家,最多走m步,每一步只能往前走或者往后走,每走到一 ...

  7. 把任意exe程序注册成windows系统服务

    某gae代理软件每次开机都需要手动启动,就算添加成开机启动项,在win8.1下权限的管理更加严格,开机时并不能成功启动软件(无人值守时开机),因此在网上搜索把exe注册成系统服务的办法,找到论坛两个帖 ...

  8. H5地理位置定位

    一:介绍使用的知识点 1.地理定位的原理 2.geolocation对象 3.Geolocation Api 4.getCurrentPosition的第一个参数 5.getCurrentPositi ...

  9. ubuntu下wordcount例子

    在/home/yuanqin/下建立file文件夹,再在文件夹建立file1.txt.file2.txt.file3.txt file1内容:hello word file2内容:hello hado ...

  10. ionic获取ios唯一设备id的解决方案

    经常有朋友来问这个问题. 每次都去解释这个问题也浪费不少时间, 所以还是开一篇文章, 把这个问题说清楚吧. 先纠正一个误区吧: 有同学可以通过ionic natvie的device插件获取. 我们在文 ...