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

[ASP.net教程]【MVC5】First AngularJS


※本文参照《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 = 1977,          RunTime = 121        },        new Movie        {          Title = "Inception",          ReleaseYear = 2010,          RunTime = 148        },        new Movie        {          Title = "Toy Story",          ReleaseYear = 1995,          RunTime = 81        } );    }  }}

在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;

image

自动生成的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) > 0;    }  }}

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.运行效果

image

点击Create按钮

image

点击Delete按钮

image

点击Details按钮

image

点击Edit按钮

image

11.注意点

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

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