※本文参照《ASP.NET MVC 5高级编程(第5版)》

1.创建Web工程

1-1.选择ASP.NET Web Application→Web API

工程名为【atTheMovie】

1-2.添加AngularJS

在Package Manager Console执行如下命令:

Install-Package AngularJS.core

1-3.添加EntityFramework

在Package Manager Console执行如下命令:

Install-Package EntityFramework

1-4.添加AngularJS.Route

Install-Package -IncludePrerelease AngularJS.Route

2.添加Model

2-1.在Models目录中添加Movie类

using System.Data.Entity;

namespace atTheMovies.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public int ReleaseYear { get; set; }
public int RunTime { get; set; }
} public class MovieDb : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
}

2-2.根据Model更新DB,生成Table

在Package Manager Console执行如下命令,会在Migrations目录中追加一个Configuration.cs的类:

Enable-Migrations -ContextTypeName atTheMovies.Models.MovieDb

修改Configuration.cs类的Seed方法如下:

namespace atTheMovies.Migrations
{
using Models;
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<atTheMovies.Models.MovieDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
} protected override void Seed(atTheMovies.Models.MovieDb context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
// context.Movies.AddOrUpdate(m => m.Title,
new Movie
{
Title = "Star Wars",
ReleaseYear = ,
RunTime =
},
new Movie
{
Title = "Inception",
ReleaseYear = ,
RunTime =
},
new Movie
{
Title = "Toy Story",
ReleaseYear = ,
RunTime =
} ); }
}
}

在Package Manager Console执行如下命令,执行上面的代码:

update-database

3.使用基架根据Model生成Controller

右击Controller目录,点击追加Controller;选择【Web API 2 Controller with actions, using Entiry Framework】;

Model选择刚刚追加的Movie;
Data context class选择Movie类中的DBContext(MovieDb);
Controller name设置为MovieController;

自动生成的MovieController的代码如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using atTheMovies.Models; namespace atTheMovies.Controllers
{
public class MovieController : ApiController
{
private MovieDb db = new MovieDb(); // GET: api/Movie
public IQueryable<Movie> GetMovies()
{
return db.Movies;
} // GET: api/Movie/5
[ResponseType(typeof(Movie))]
public IHttpActionResult GetMovie(int id)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return NotFound();
} return Ok(movie);
} // PUT: api/Movie/5
[ResponseType(typeof(void))]
public IHttpActionResult PutMovie(int id, Movie movie)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != movie.Id)
{
return BadRequest();
} db.Entry(movie).State = EntityState.Modified; try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(id))
{
return NotFound();
}
else
{
throw;
}
} return StatusCode(HttpStatusCode.NoContent);
} // POST: api/Movie
[ResponseType(typeof(Movie))]
public IHttpActionResult PostMovie(Movie movie)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Movies.Add(movie);
db.SaveChanges(); return CreatedAtRoute("DefaultApi", new { id = movie.Id }, movie);
} // DELETE: api/Movie/5
[ResponseType(typeof(Movie))]
public IHttpActionResult DeleteMovie(int id)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return NotFound();
} db.Movies.Remove(movie);
db.SaveChanges(); return Ok(movie);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
} private bool MovieExists(int id)
{
return db.Movies.Count(e => e.Id == id) > ;
}
}
}

4.修改既存的Index.cshtml代码

这里已经把所有相关的JS追加好了,具体代码见后面部分。

@section scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Client/Scripts/atTheMovies.js"></script>
<script src="~/Client/Scripts/ListController.js"></script>
<script src="~/Client/Scripts/DetailsController.js"></script>
<script src="~/Client/Scripts/movieService.js"></script>
<script src="~/Client/Scripts/EditController.js"></script>
}
<div ng-app="atTheMovies">
<ng-view></ng-view>
</div>

5.注册模块、路由、常量等

5-1.创建Client\Scripts目录;追加atTheMovies.js;

(function () {
// 创建了一个新模块atTheMovies
// 第二个参数为空[],代表这个模块依赖于核心Angular模块ng
// var app = angular.module("atTheMovies", []); // 添加依赖模块 ngRoute 路由
var app = angular.module("atTheMovies", ["ngRoute"]); var config = function ($routeProvider) {
$routeProvider
.when("/list", { templateUrl: "/client/views/list.html" })
.when("/details/:id", { templateUrl: "/client/views/details.html" })
.otherwise({ redirectTo: "/list" });
}; app.config(config);
// 注册常量值
app.constant("movieApiUrl", "/api/movie/");
}());

6.创建Service

6-1.在Client\Scripts目录中追加movieService.js;

(function (app) {
var movieService = function ($http, movieApiUrl) {
var getAll = function () {
return $http.get(movieApiUrl);
}; var getById = function (id) {
return $http.get(movieApiUrl + id);
}; var update = function (movie) {
return $http.put(movieApiUrl + movie.Id, movie);
}; var create = function (movie) {
return $http.post(movieApiUrl, movie);
}; var destroy = function (movie) {
return $http.delete(movieApiUrl + movie.Id);
}; return {
getAll: getAll,
getById: getById,
update: update,
create: create,
delete: destroy,
};
}; app.factory("movieService", movieService);
})(angular.module("atTheMovies"));

7.创建ListController和ListView

7-1.在Client\Scripts目录中追加ListController.js;

(function (app) {
//var ListController = function ($scope, $http) {
// $scope.message = "Hello, World!";
// $http.get("/api/movie").success(function (data) {
// $scope.movies = data;
// });
//};
//ListController.$inject = ["$scope", "$http"]; // 使用movieService
var ListController = function ($scope, movieService) {
movieService
.getAll()
.success(function (data) {
$scope.movies = data;
}); $scope.create = function () {
$scope.edit = {
movie: {
Title: "",
RunTime: 0,
ReleaseYear: new Date().getFullYear()
}
};
}; $scope.delete = function (movie) {
movieService.delete(movie)
.success(function () {
removeMovieById(movie.Id);
});
}; var removeMovieById = function (id) {
for (var i = 0; i < $scope.movies.length; i++) {
if ($scope.movies[i].Id == id) {
$scope.movies.splice(i, 1);
break;
}
}
};
}; // 注册新控制器
// 参数:
// 控制器名称
// 与这个名称关联的构造函数
app.controller("ListController", ListController); })(angular.module("atTheMovies"));
// 使用临时的调用函数表达式来代替创建全局变量 // 还有一种方法可以获取atTheMovies的引用
// (function (app) {
// var app = angular.module("atTheMovies");
// }());.

7-2.在Client\Views目录中追加list.html;

<div ng-controller="ListController">
<table class="table" >
<tr ng-repeat="movie in movies">
<td>{{movie.Title}}</td>
<td>
<a class="btn btn-default" href="#/details/{{movie.Id}}">Details</a>
<button class="btn btn-default" ng-click="delete(movie)">Delete</button>
</td>
</tr>
</table>
<button class="btn btn-default" ng-click="create()">Create</button>
<div ng-include="'/Client/views/edit.html'"></div>
</div>

8.创建DetailsController和DetailsView

8-1.在Client\Scripts目录中追加DetailsController.js;

(function (app) {
//var DetailsController = function ($scope, $http, $routeParams) {
// var id = $routeParams.id;
// $http.get("/api/movie/" + id)
// .success(function (data) {
// $scope.movie = data;
// });
//}; // 使用movieService
var DetailsController = function ($scope, $routeParams, movieService) {
var id = $routeParams.id;
movieService
.getById(id)
.success(function (data) {
$scope.movie = data;
}); $scope.edit = function () {
$scope.edit.movie = angular.copy($scope.movie);
};
}; app.controller("DetailsController", DetailsController);
})(angular.module("atTheMovies"));

8-2.在Client\Views目录中追加details.html;

<div ng-controller="DetailsController">
<h2>{{movie.Title}}</h2>
<div>
Released in {{movie.ReleaseYear}}.
</div>
<div>
{{movie.RunTime}} minutes long.
</div>
<button ng-click="edit()">Edit</button>
<div ng-include="'/Client/views/edit.html'"></div>
</div>

9.创建EditController和EditView

9-1.在Client\Scripts目录中追加EditController.js;

(function (app) {
var EditController = function ($scope, movieService) {
$scope.isEditable = function () {
return $scope.edit && $scope.edit.movie;
}; $scope.cancel = function () {
$scope.edit.movie = null;
}; $scope.save = function () {
if ($scope.edit.movie.Id) {
updateMovie();
} else {
createMovie();
}
}; var updateMovie = function () {
movieService.update($scope.edit.movie)
.success(function () {
angular.extend($scope.movie, $scope.edit.movie);
$scope.edit.movie = null;
});
}; var createMovie = function () {
movieService.create($scope.edit.movie)
.success(function (movie) {
$scope.movies.push(movie);
$scope.edit.movie = null;
});
}; }; app.controller("EditController", EditController); })(angular.module("atTheMovies"));

9-2.在Client\Views目录中追加edit.html;

<div ng-controller="EditController">
<form ng-show="isEditable()">
<fieldset>
<div class="form-group">
<label for="title">
Title
</label>
<input id="title" type="text" ng-model="edit.movie.Title" required class="form-control" />
</div>
<div class="form-group">
<label for="release">
Release Year
</label>
<input id="release" type="number" ng-model="edit.movie.ReleaseYear" required min="1900" max="2030" class="form-control" />
</div>
<div class="form-group">
<label for="runtime">
Length
</label>
<input id="runtime" type="number" ng-model="edit.movie.RunTime" required min="0" max="500" class="form-control" />
</div>
<button class="btn btn-default" ng-click="save()">Save</button>
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
</fieldset>
</form>
</div>

10.运行效果

点击Create按钮

点击Delete按钮

点击Details按钮

点击Edit按钮

11.注意点

11-1.JS模型中属性名的大小写

一定要保持和CS代码中模型属性名大小写一致;否则会导致画面上显示不出来值或者画面上的值没有更新到DB中。

【MVC5】First AngularJS的更多相关文章

  1. 【MVC5】画面多按钮提交

    画面上有个多个按钮时,如何绑定到各自的Action上? 1.追加如下MultipleButtonAttribute类 1 using System; 2 using System.Reflection ...

  2. 【MVC5】对MySql数据库使用EntityFramework

    版本: MySql : 5.6.3 MySql.Data : 6.9.7 MVC : 5 EntityFramework : 6.1.3 VS : 2015 步骤: 1.安装[mysql-connec ...

  3. 【MVC5】使用域用户登录+记住我

    1.配置Web.config文件 添加域链接字符串 <connectionStrings> <add name="ADConnectionString" conn ...

  4. 【MVC5】使用权限+角色

    1.在Ticket中设置用户角色 在权限的Ticket中设置用户的角色(这里是逗号分割). List<string> roles = new List<string>(); i ...

  5. 【MVC5】后台修改的Model值反映不到客户端的问题

    画面上的检索结果有翻页功能,就在画面上追加了几个隐藏控件保存上次检索时的检索条件. 检索时更新这些隐藏控件的值,Debug时确实把Model中对应的属性值变掉了,但是到了客户端又变回之前的值了. 百思 ...

  6. 【MVC5】日期选择控件DatePicker

    项目中使用了Bootstrap,日期控件就选择了依赖于bootstrap的DatePicker. 在App_Start\BundleConfig.cs中引用css和js文件: bundles.Add( ...

  7. 【MVC5】ASP.NET MVC 项目笔记汇总

    ASP.NET MVC 5 + EntityFramework 6 + MySql 先写下列表,之后慢慢补上~ 对MySql数据库使用EntityFramework 使用域用户登录+记住我 画面多按钮 ...

  8. 【转】Laravel+Angularjs+D3打造可视化数据,RESTful+Ajax

    http://897371388.iteye.com/blog/1975351 大致思路也就是下面,由于最近在学Laravel也在学Angularjs,加上之前做的项目用到了d3. 原来的方案如下: ...

  9. 【转载】图灵AngularJS入门教程

    摘自图灵的AngularJS入门教程:http://www.ituring.com.cn/article/13471 感觉非常不错,所以推荐到首页一下! (一)Hello World! 开始学习Ang ...

随机推荐

  1. webdiyer aspnet pager最近又用这个。还是记录下。

    这个是页面里的代码需要在上面引入: <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer&quo ...

  2. PHP会话控制

         会话控制的思想是指能够在网站中根据一个会话跟踪用户.      PHP的会话是通过唯一的会话ID来驱动的.会话ID是一个加密的随机数字.它由PHP生成,在会话的生命周期中都会保存在客户端.它 ...

  3. MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC(转)

    原文转自 https://blog.csdn.net/albertsh/article/details/52838419 1.使用标准Windows库 使用WINDOWS SDK API库,不使用MF ...

  4. libv4l 库【转】

    转自:http://www.cnblogs.com/emouse/archive/2013/03/05/2944522.html V4L2摸索了两天还是一头雾水,今天调试一个程序发现两个头文件: #i ...

  5. Android平台开发-WIFI 驱动移植 -- 详细

    一.WIFI的基本架构(代码路径)     1.WIFI Settings应用程序:       packages/apps/Settings/src/com/android/settings/wif ...

  6. jquery做一个表单验证

    正则表达式的写法: var re=new RegExp('规则', '可选参数');var re=/规则/参数;(这个最常用) 正则表达式的规则 和其他语言的正则表达式规则一样,可以参考我的另一边博文 ...

  7. PHP面向对象知识点总结

    1.$this是什么 当前类实例化的对象 2.访问对象中的成员 对象->成员 3.构造方法 通常用来初始化对象的属性,不用把属性写死,不同的对象就有了不同的属性 4.get.set的用法 通常将 ...

  8. Netty源码学习(六)ChannelPipeline

    0. ChannelPipeline简介 ChannelPipeline = Channel + Pipeline,也就是说首先它与Channel绑定,然后它是起到类似于管道的作用:字节流在Chann ...

  9. luogu P1417 烹调方案

    题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...

  10. 【BZOJ4458】GTY的OJ

    题面 Description 身为IOI金牌的gtyzs有自己的一个OJ,名曰GOJ.GOJ上的题目可谓是高质量而又经典,他在他的OJ里面定义了一个树形的分类目录,且两个相同级别的目录是不会重叠的.比 ...