• 对一个前端使用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/

    这里记录下对此项目的理解。分为如下几篇:

    ● 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(1)--领域、Repository、Service

    ● 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(2)--依赖倒置、Bundling、视图模型验证、视图模型和领域模型映射、自定义handler

    ● 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(3)--主页面布局

    ● 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(4)--Movie增改查以及上传图片

    显示带分页过滤条件的Movie

    /关于分页,通常情况下传的参数包括:当前页、页容量
    //关于过滤:传过滤字符串
    [AllowAnonymous]
    [Route("{page:int=0}/{pageSize=3}/{filter?}")] //给路由中的变量赋上初值
    public HttpResponseMessage Get(HttpRequestMessage request, int? page, int? pageSize, string filter = null)
    {
        int currentPage = page.Value; // 当前页
        int currentPageSize = pageSize.Value;//页容量
    
        return CreateHttpResponse(request, () =>
        {
            HttpResponseMessage response = null;
            List<Movie> movies = null;
            int totalMovies = new int();//总数
    
            if (!string.IsNullOrEmpty(filter)) //如果有过滤条件
            {
                movies = _moviesRepository.GetAll()
                    .OrderBy(m => m.ID)
                    .Where(m => m.Title.ToLower()
                    .Contains(filter.ToLower().Trim()))
                    .ToList();
            }
            else
            {
                movies = _moviesRepository.GetAll().ToList();
            }
    
            totalMovies = movies.Count(); //总数量
            movies = movies.Skip(currentPage * currentPageSize)
                    .Take(currentPageSize)
                    .ToList();
    
            //领域模型转换成视图模型
            IEnumerable<MovieViewModel> moviesVM = Mapper.Map<IEnumerable<Movie>, IEnumerable<MovieViewModel>>(movies);
    
            PaginationSet<MovieViewModel> pagedSet = new PaginationSet<MovieViewModel>()
            {
                Page = currentPage,
                TotalCount = totalMovies,
                TotalPages = (int)Math.Ceiling((decimal)totalMovies / currentPageSize),
                Items = moviesVM
            };
    
            //再把视图模型和分页等数据放在响应中返回
            response = request.CreateResponse<PaginationSet<MovieViewModel>>(HttpStatusCode.OK, pagedSet);
    
            return response;
        });
    }

    PagenationSet<T>是对分页和领域模型集合的一个封装。

    namespace HomeCinema.Web.Infrastructure.Core
    {
        public class PaginationSet<T>
        {
            public int Page { get; set; }
    
            public int Count
            {
                get
                {
                    return (null != this.Items) ? this.Items.Count() : 0;
                }
            }
    
            public int TotalPages { get; set; }
            public int TotalCount { get; set; }
    
            public IEnumerable<T> Items { get; set; }
        }
    }

    界面部分,首页中使用了一个自定义的directive。

    <side-bar></side-bar>

    在side-bar所对应的html部分提供了获取所有Movie的链接。

    <a ng-href="#/movies/">Movies<i class="fa fa-film fa-fw pull-right"></i></a>

    而在app.js的路由设置中:

    .when("/movies", {
        templateUrl: "scripts/spa/movies/movies.html",
        controller: "moviesCtrl"
    })

    先来看scripts/spa/movies/movies.html页面摘要:

    <!--过滤-->
    <input id="inputSearchMovies" type="search" ng-model="filterMovies" placeholder="Filter, search movies..">
    <button class="btn btn-primary" ng-click="search();"></button>
    <button class="btn btn-primary" ng-click="clearSearch();"></button>
    
    <!--列表-->
    <a class="pull-left" ng-href="#/movies/{{movie.ID}}" title="View {{movie.Title}} details">
        <img class="media-object" height="120" ng-src="../../Content/images/movies/{{movie.Image}}" alt="" />
    </a>
    <h4 class="media-heading">{{movie.Title}}</h4>
    <strong>{{movie.Director}}</strong>
    <strong>{{movie.Writer}}</strong>
    <strong>{{movie.Producer}}</strong>
    <a class="fancybox-media" ng-href="{{movie.TrailerURI}}">Trailer<i class="fa fa-video-camera fa-fw"></i></a>
    <span component-rating="{{movie.Rating}}"></span>
    <label class="label label-info">{{movie.Genre}}</label>
    <available-movie is-available="{{movie.IsAvailable}}"></available-movie>
    
    <!--分页-->
    <custom-pager page="{{page}}" custom-path="{{customPath}}" pages-count="{{pagesCount}}" total-count="{{totalCount}}" search-func="search(page)"></custom-pager>

    再来看对应的moviesCtrl控制器:

    (function (app) {
        'use strict';
    
        app.controller('moviesCtrl', moviesCtrl);
    
        moviesCtrl.$inject = ['$scope', 'apiService','notificationService'];
    
        //所有变量都赋初值pageClass, loadingMovies, page, pagesCount, movies, search方法,clearSearch方法
        function moviesCtrl($scope, apiService, notificationService) {
            $scope.pageClass = 'page-movies';
            $scope.loadingMovies = true;
            $scope.page = 0;
            $scope.pagesCount = 0;
            
            $scope.Movies = [];
    
            $scope.search = search;
            $scope.clearSearch = clearSearch;
    
            //当前页索引作为参数传递
            function search(page) {
                page = page || 0;
    
                $scope.loadingMovies = true;
    
                //这里的object键值将被放在路由中以便action方法接收
                var config = {
                    params: {
                        page: page,
                        pageSize: 6,
                        filter: $scope.filterMovies
                    }
                };
    
                apiService.get('/api/movies/', config,
                moviesLoadCompleted,
                moviesLoadFailed);
            }
    
            function moviesLoadCompleted(result) {
                $scope.Movies = result.data.Items;
                $scope.page = result.data.Page;
                $scope.pagesCount = result.data.TotalPages;
                $scope.totalCount = result.data.TotalCount;
                $scope.loadingMovies = false;
    
                if ($scope.filterMovies && $scope.filterMovies.length)
                {
                    notificationService.displayInfo(result.data.Items.length + ' movies found');
                }
                
            }
    
            function moviesLoadFailed(response) {
                notificationService.displayError(response.data);
            }
    
            function clearSearch() {
                $scope.filterMovies = '';
                search();
            }
    
            $scope.search();
        }
    
    })(angular.module('homeCinema'));

    然后对于分页,当然需要自定义directive,如下:

    <custom-pager page="{{page}}" custom-path="{{customPath}}" pages-count="{{pagesCount}}" total-count="{{totalCount}}" search-func="search(page)"></custom-pager>

    对应的html部分来自spa/layout/pager.html

    <div>
        <div ng-hide="(!pagesCount || pagesCount < 2)" style="display:inline">
            <ul class="pagination pagination-sm">
                <li><a ng-hide="page == 0" ng-click="search(0)"><<</a></li>
                <li><a ng-hide="page == 0" ng-click="search(page-1)"><</a></li>
                <li ng-repeat="n in range()" ng-class="{active: n == page}">
                    <a ng-click="search(n)" ng-if="n != page">{{n+1}}</a>
                    <span ng-if="n == page">{{n+1}}</span>
                </li>
                <li><a ng-hide="page == pagesCount - 1" ng-click="search(pagePlus(1))">></a></li>
                <li><a ng-hide="page == pagesCount - 1" ng-click="search(pagesCount - 1)">>></a></li>
            </ul>
        </div>
    </div>

    自定义的directive部分写在了spa/layout/customPager.directive.js里:

    (function(app) {
        'use strict';
    
        app.directive('customPager', customPager);
    
        function customPager() {
            return {
                scope: {
                    page: '@',
                    pagesCount: '@',
                    totalCount: '@',
                    searchFunc: '&',
                    customPath: '@'
                },
                replace: true,
                restrict: 'E',
                templateUrl: '/scripts/spa/layout/pager.html',
                controller: ['$scope', function ($scope) {
                    $scope.search = function (i) {
                        if ($scope.searchFunc) {
                            $scope.searchFunc({ page: i });
                        }
                    };
    
                    $scope.range = function () {
                        if (!$scope.pagesCount) { return []; }
                        var step = 2;
                        var doubleStep = step * 2;
                        var start = Math.max(0, $scope.page - step);
                        var end = start + 1 + doubleStep;
                        if (end > $scope.pagesCount) { end = $scope.pagesCount; }
    
                        var ret = [];
                        for (var i = start; i != end; ++i) {
                            ret.push(i);
                        }
    
                        return ret;
                    };
    
                    $scope.pagePlus = function(count)
                    {
                        return +$scope.page + count;
                    }
                }]
            }
        }
    
    })(angular.module('common.ui'));

    点击Movie列表中某一项的图片来到明细页

    html部分:

    <a class="pull-left" ng-href="#/movies/{{movie.ID}}" title="View {{movie.Title}} details">
        <img class="media-object" height="120" ng-src="../../Content/images/movies/{{movie.Image}}" alt="" />
    </a>

    在app.js中已经定义了路由规则:

    .when("/movies/:id", {
        templateUrl: "scripts/spa/movies/details.html",
        controller: "movieDetailsCtrl",
        resolve: { isAuthenticated: isAuthenticated }
    })

    来看API部分:

    [Route("details/{id:int}")]
    public HttpResponseMessage Get(HttpRequestMessage request, int id)
    {
        return CreateHttpResponse(request, () =>
        {
            HttpResponseMessage response = null;
            var movie = _moviesRepository.GetSingle(id);
    
            MovieViewModel movieVM = Mapper.Map<Movie, MovieViewModel>(movie);
    
            response = request.CreateResponse<MovieViewModel>(HttpStatusCode.OK, movieVM);
    
            return response;
        });
    }

    再来看明细部分的页面摘要:scripts/spa/movies/details.html

    <h5>{{movie.Title}}</h5>
    <div class="panel-body" ng-if="!loadingMovie">
        <a class="pull-right" ng-href="#/movies/{{movie.ID}}" title="View {{movie.Title}} details">
            <img class="media-object" height="120" ng-src="../../Content/images/movies/{{movie.Image}}" alt="" />
        </a>
         <h4 class="media-heading">{{movie.Title}}</h4>
        Directed by: <label>{{movie.Director}}</label><br />
        Written by: <label>{{movie.Writer}}</label><br />
        Produced by: <label>{{movie.Producer}}</label><br />
        Rating: <span component-rating='{{movie.Rating}}'></span>
        <br />
        <label class="label label-info">{{movie.Genre}}</label>
        <available-movie is-available="{{movie.IsAvailable}}"></available-movie>
        
        <a ng-href="{{movie.TrailerURI}}" >View Trailer <i class="fa fa-video-camera pull-right"></i></a>
        <a ng-href="#/movies/edit/{{movie.ID}}" class="btn btn-default">Edit movie </a>
    </div>

    控制器部分为:scripts/spa/movies/movieDetailsCtrl.js

    (function (app) {
        'use strict';
    
        app.controller('movieDetailsCtrl', movieDetailsCtrl);
    
        movieDetailsCtrl.$inject = ['$scope', '$location', '$routeParams', '$modal', 'apiService', 'notificationService'];
    
        function movieDetailsCtrl($scope, $location, $routeParams, $modal, apiService, notificationService) {
            $scope.pageClass = 'page-movies';
            $scope.movie = {};
            $scope.loadingMovie = true;
            $scope.loadingRentals = true;
            $scope.isReadOnly = true;
            $scope.openRentDialog = openRentDialog;
            $scope.returnMovie = returnMovie;
            $scope.rentalHistory = [];
            $scope.getStatusColor = getStatusColor;
            $scope.clearSearch = clearSearch;
            $scope.isBorrowed = isBorrowed;
    
            function loadMovie() {
    
                $scope.loadingMovie = true;
    
                apiService.get('/api/movies/details/' + $routeParams.id, null,
                movieLoadCompleted,
                movieLoadFailed);
            }
    
    
            function movieLoadCompleted(result) {
                $scope.movie = result.data;
                $scope.loadingMovie = false;
            }
    
            function movieLoadFailed(response) {
                notificationService.displayError(response.data);
            }
    
           loadMovie();
        }
    
    })(angular.module('homeCinema'));

    更新

    在Movie的明细页给出了编辑按钮:

    <a ng-href="#/movies/edit/{{movie.ID}}" class="btn btn-default">Edit movie </a>

    而在app.js的路由设置中:

    .when("/movies/edit/:id", {
        templateUrl: "scripts/spa/movies/edit.html",
        controller: "movieEditCtrl"
    })

    来看编辑明细页摘要:scripts/spa/movies/edit.html

    <img ng-src="../../Content/images/movies/{{movie.Image}}" class="avatar img-responsive" alt="avatar">
    <input type="file" ng-file-select="prepareFiles($files)">
    
    <form class="form-horizontal" role="form" novalidate angular-validator name="editMovieForm" angular-validator-submit="UpdateMovie()">
    
        <input class="form-control" name="title" type="text" ng-model="movie.Title" validate-on="blur" required required-message="'Movie title is required'">
        
        <select ng-model="movie.GenreId" class="form-control black" ng-options="option.ID as option.Name for option in genres" required></select>
        <input type="hidden" name="GenreId" ng-value="movie.GenreId" />
        
        <input class="form-control" type="text" ng-model="movie.Director" name="director" validate-on="blur" required required-message="'Movie director is required'">
        
        <input class="form-control" type="text" ng-model="movie.Writer" name="writer" validate-on="blur" required required-message="'Movie writer is required'">
        
         <input class="form-control" type="text" ng-model="movie.Producer" name="producer" validate-on="blur" required required-message="'Movie producer is required'">
         
         <input type="text" class="form-control" name="dateReleased" datepicker-popup="{{format}}" ng-model="movie.ReleaseDate" is-open="datepicker.opened" datepicker-options="dateOptions" ng-required="true" datepicker-append-to-body="true" close-text="Close" validate-on="blur" required required-message="'Date Released is required'" />
        <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="openDatePicker($event)"></button>
        </span>
        
        <input class="form-control" type="text" ng-model="movie.TrailerURI" name="trailerURI" validate-on="blur" required required-message="'Movie trailer is required'" ng-pattern="/^(https?://)?(www.youtube.com|youtu.?be)/.+$/" invalid-message="'You must enter a valid YouTube URL'">
        
        <textarea class="form-control" ng-model="movie.Description" name="description" rows="3" validate-on="blur" required required-message="'Movie description is required'" />
        
        <span component-rating="{{movie.Rating}}" ng-model="movie.Rating" class="form-control"></span>
        
        <input type="submit" class="btn btn-primary" value="Update" />
        <a class="btn btn-default" ng-href="#/movies/{{movie.ID}}">Cancel</a>
    </form>

    再来看编辑明细页控制器:scripts/spa/movies/movieEditCtrl.js

    (function (app) {
        'use strict';
    
        app.controller('movieEditCtrl', movieEditCtrl);
    
        movieEditCtrl.$inject = ['$scope', '$location', '$routeParams', 'apiService', 'notificationService', 'fileUploadService'];
    
        function movieEditCtrl($scope, $location, $routeParams, apiService, notificationService, fileUploadService) {
            $scope.pageClass = 'page-movies';
            $scope.movie = {};
            $scope.genres = [];
            $scope.loadingMovie = true;
            $scope.isReadOnly = false;
            $scope.UpdateMovie = UpdateMovie;
            $scope.prepareFiles = prepareFiles;
            $scope.openDatePicker = openDatePicker;
    
            $scope.dateOptions = {
                formatYear: 'yy',
                startingDay: 1
            };
            $scope.datepicker = {};
    
            var movieImage = null;
    
            //加载movie
            function loadMovie() {
    
                $scope.loadingMovie = true;
    
                apiService.get('/api/movies/details/' + $routeParams.id, null,
                movieLoadCompleted,
                movieLoadFailed);
            }
    
            //加载movie完成后加载genre
            function movieLoadCompleted(result) {
                $scope.movie = result.data;
                $scope.loadingMovie = false;
    
                //再加载genre
                loadGenres();
            }
    
            function movieLoadFailed(response) {
                notificationService.displayError(response.data);
            }
    
            function genresLoadCompleted(response) {
                $scope.genres = response.data;
            }
    
            function genresLoadFailed(response) {
                notificationService.displayError(response.data);
            }
    
            function loadGenres() {
                apiService.get('/api/genres/', null,
                genresLoadCompleted,
                genresLoadFailed);
            }
    
            function UpdateMovie() {
                //上传图片
                if (movieImage) {
                    fileUploadService.uploadImage(movieImage, $scope.movie.ID, UpdateMovieModel);
                }
                else
                    UpdateMovieModel();
            }
    
            //实施更新
            function UpdateMovieModel() {
                apiService.post('/api/movies/update', $scope.movie,
                updateMovieSucceded,
                updateMovieFailed);
            }
    
            function prepareFiles($files) {
                movieImage = $files;
            }
    
            function updateMovieSucceded(response) {
                console.log(response);
                notificationService.displaySuccess($scope.movie.Title + ' has been updated');
                $scope.movie = response.data;
                movieImage = null;
            }
    
            function updateMovieFailed(response) {
                notificationService.displayError(response);
            }
    
            function openDatePicker($event) {
                $event.preventDefault();
                $event.stopPropagation();
    
                $scope.datepicker.opened = true;
            };
    
            loadMovie();
        }
    
    })(angular.module('homeCinema'));

    对于上传图片,放在了一个自定义的服务中,在spa/services/fileUploadService.js中:

    (function (app) {
        'use strict';
    
        app.factory('fileUploadService', fileUploadService);
    
        fileUploadService.$inject = ['$rootScope', '$http', '$timeout', '$upload', 'notificationService'];
    
        function fileUploadService($rootScope, $http, $timeout, $upload, notificationService) {
    
            $rootScope.upload = [];
    
            var service = {
                uploadImage: uploadImage
            }
    
            function uploadImage($files, movieId, callback) {
                //$files: an array of files selected
                for (var i = 0; i < $files.length; i++) {
                    var $file = $files[i];
                    (function (index) {
                        $rootScope.upload[index] = $upload.upload({
                            url: "api/movies/images/upload?movieId=" + movieId, // webapi url
                            method: "POST",
                            file: $file
                        }).progress(function (evt) {
                        }).success(function (data, status, headers, config) {
                            // file is uploaded successfully
                            notificationService.displaySuccess(data.FileName + ' uploaded successfully');
                            callback();
                        }).error(function (data, status, headers, config) {
                            notificationService.displayError(data.Message);
                        });
                    })(i);
                }
            }
    
            return service;
        }
    
    })(angular.module('common.core'));

    在后端API中,对应的更新和上传图片action如下:

    [HttpPost]
    [Route("update")]
    public HttpResponseMessage Update(HttpRequestMessage request, MovieViewModel movie)
    {
        return CreateHttpResponse(request, () =>
        {
            HttpResponseMessage response = null;
    
            if (!ModelState.IsValid)
            {
                response = request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
            else
            {
                var movieDb = _moviesRepository.GetSingle(movie.ID);
                if (movieDb == null)
                    response = request.CreateErrorResponse(HttpStatusCode.NotFound, "Invalid movie.");
                else
                {
                    movieDb.UpdateMovie(movie);
                    movie.Image = movieDb.Image;
                    _moviesRepository.Edit(movieDb);
    
                    _unitOfWork.Commit();
                    response = request.CreateResponse<MovieViewModel>(HttpStatusCode.OK, movie);
                }
            }
    
            return response;
        });
    }
    
    [MimeMultipart]
    [Route("images/upload")]
    public HttpResponseMessage Post(HttpRequestMessage request, int movieId)
    {
        return CreateHttpResponse(request, () =>
        {
            HttpResponseMessage response = null;
    
            var movieOld = _moviesRepository.GetSingle(movieId);
            if (movieOld == null)
                response = request.CreateErrorResponse(HttpStatusCode.NotFound, "Invalid movie.");
            else
            {
                var uploadPath = HttpContext.Current.Server.MapPath("~/Content/images/movies");
    
                var multipartFormDataStreamProvider = new UploadMultipartFormProvider(uploadPath);
    
                // Read the MIME multipart asynchronously 
                Request.Content.ReadAsMultipartAsync(multipartFormDataStreamProvider);
    
                string _localFileName = multipartFormDataStreamProvider
                    .FileData.Select(multiPartData => multiPartData.LocalFileName).FirstOrDefault();
    
                // Create response
                FileUploadResult fileUploadResult = new FileUploadResult
                {
                    LocalFilePath = _localFileName,
    
                    FileName = Path.GetFileName(_localFileName),
    
                    FileLength = new FileInfo(_localFileName).Length
                };
    
                // update database
                movieOld.Image = fileUploadResult.FileName;
                _moviesRepository.Edit(movieOld);
                _unitOfWork.Commit();
    
                response = request.CreateResponse(HttpStatusCode.OK, fileUploadResult);
            }
    
            return response;
        });
    }

    添加

    在sidebar的html部分为:

    <li><a ng-href="#/movies/add">Add movie</a></li>

    在app.js的路由设置中:

    .when("/movies/add", {
        templateUrl: "scripts/spa/movies/add.html",
        controller: "movieAddCtrl",
        resolve: { isAuthenticated: isAuthenticated }
    })

    scripts/spa/movies/add.html部分与edit.html部分相似。


    scripts/spa/movies/movieAddCtrl.js中:

    (function (app) {
        'use strict';
    
        app.controller('movieAddCtrl', movieAddCtrl);
    
        movieAddCtrl.$inject = ['$scope', '$location', '$routeParams', 'apiService', 'notificationService', 'fileUploadService'];
    
        function movieAddCtrl($scope, $location, $routeParams, apiService, notificationService, fileUploadService) {
    
            $scope.pageClass = 'page-movies';
            $scope.movie = { GenreId: 1, Rating: 1, NumberOfStocks: 1 };
    
            $scope.genres = [];
            $scope.isReadOnly = false;
            $scope.AddMovie = AddMovie;
            $scope.prepareFiles = prepareFiles;
            $scope.openDatePicker = openDatePicker;
            $scope.changeNumberOfStocks = changeNumberOfStocks;
    
            $scope.dateOptions = {
                formatYear: 'yy',
                startingDay: 1
            };
            $scope.datepicker = {};
    
            var movieImage = null;
    
            function loadGenres() {
                apiService.get('/api/genres/', null,
                genresLoadCompleted,
                genresLoadFailed);
            }
    
            function genresLoadCompleted(response) {
                $scope.genres = response.data;
            }
    
            function genresLoadFailed(response) {
                notificationService.displayError(response.data);
            }
    
            function AddMovie() {
                AddMovieModel();
            }
    
            function AddMovieModel() {
                apiService.post('/api/movies/add', $scope.movie,
                addMovieSucceded,
                addMovieFailed);
            }
    
            function prepareFiles($files) {
                movieImage = $files;
            }
    
            function addMovieSucceded(response) {
                notificationService.displaySuccess($scope.movie.Title + ' has been submitted to Home Cinema');
                $scope.movie = response.data;
                
                //添加movie成功后再上传图片
                if (movieImage) {
                    fileUploadService.uploadImage(movieImage, $scope.movie.ID, redirectToEdit);
                }
                else
                    redirectToEdit();
            }
    
            function addMovieFailed(response) {
                console.log(response);
                notificationService.displayError(response.statusText);
            }
    
            function openDatePicker($event) {
                $event.preventDefault();
                $event.stopPropagation();
    
                $scope.datepicker.opened = true;
            };
    
            function redirectToEdit() {
                $location.url('movies/edit/' + $scope.movie.ID);
            }
    
            function changeNumberOfStocks($vent)
            {
                var btn = $('#btnSetStocks'),
                oldValue = $('#inputStocks').val().trim(),
                newVal = 0;
    
                if (btn.attr('data-dir') == 'up') {
                    newVal = parseInt(oldValue) + 1;
                } else {
                    if (oldValue > 1) {
                        newVal = parseInt(oldValue) - 1;
                    } else {
                        newVal = 1;
                    }
                }
                $('#inputStocks').val(newVal);
                $scope.movie.NumberOfStocks = newVal;
                console.log($scope.movie);
            }
    
            loadGenres();
        }
    
    })(angular.module('homeCinema'));

    后端对应的添加API部分:

    [HttpPost]
    [Route("add")]
    public HttpResponseMessage Add(HttpRequestMessage request, MovieViewModel movie)
    {
        return CreateHttpResponse(request, () =>
        {
            HttpResponseMessage response = null;
    
            if (!ModelState.IsValid)
            {
                response = request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
            else
            {
                Movie newMovie = new Movie();
                newMovie.UpdateMovie(movie);
    
                for (int i = 0; i < movie.NumberOfStocks; i++)
                {
                    Stock stock = new Stock()
                    {
                        IsAvailable = true,
                        Movie = newMovie,
                        UniqueKey = Guid.NewGuid()
                    };
                    newMovie.Stocks.Add(stock);
                }
    
                _moviesRepository.Add(newMovie);
    
                _unitOfWork.Commit();
    
                // Update view model
                movie = Mapper.Map<Movie, MovieViewModel>(newMovie);
                response = request.CreateResponse<MovieViewModel>(HttpStatusCode.Created, movie);
            }
    
            return response;
        });
    }

    本系列结束~

  • 相关阅读:
    资源 | TensorFlow推出新工具Seedbank:即刻使用的预训练模型库【转】
    Vim 基本設置 – 使用Vim-plug管理插件 (3)【转】
    Linux kernel 编译问题记录【转】
    深度学习(四)卷积神经网络入门学习(1)【转】
    深度学习:Keras入门(二)之卷积神经网络(CNN)【转】
    深度学习:Keras入门(一)之基础篇【转】
    CNN笔记:通俗理解卷积神经网络【转】
    [Deep Learning] 神经网络基础【转】
    一文弄懂神经网络中的反向传播法——BackPropagation【转】
    Testin
  • 原文地址:https://www.cnblogs.com/darrenji/p/4945763.html
Copyright © 2020-2023  润新知