第十話 Asp.Net MVC 3.0 【MVC項目實戰の六】


今天主要演示的就是前面項目的后台功能的開發,在后台我們搞了一個上傳圖片的功能,具體的下面開始!(這次東東可能有點多,想學習的同學可要耐心的看哦!)

考慮到是我們需要搞一個圖片上傳的功能,所以我們的表肯定也添加新的字段等;還有我們后台要有區別於前台的模版等!接下來就一步一步的完善吧!

首先添加管理目錄,我們習慣用下面的頁面來管理我們的數據,如下圖1.

圖1.這是一個CRUD的草圖(CRUD:它代表創建(Create)、更新(Update)、讀取(Read)和刪除(Delete)操作,這里是簡稱)。

接下來創建一個CURD的Controller(控制器),在我們的Web項目的Controllers文件夾下創建,如下圖2.

圖2.命名為"AdminController",具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;

namespace SportsStore.WebUI.Controllers
{
    [Authorize]
    public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
        /// <summary>
        /// 展示商品列表頁面
        /// </summary>
        /// <returns>商品的列表</returns>
        public ViewResult Index()
        {
            return this.View(this.repository.Products);
        }
    }
}

這里我們寫了一個很簡單的Index Action(方法),現在先開始弄一個簡單的后台頁面出來,我們創建一個相應的視圖!哦,忘了。我們后台又有卻別於前台的模版頁面,所以我們新建一個模版頁面如下圖3.

圖3.(在們web項目的Views/Shared文件夾下創建),創建好我們對模版修改如下:

<!DOCTYPE html>

<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Admin.css")" rel="Stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
</head>
<body>
    <div> @if (TempData["message"]!=null) { <div class="Message">@TempData["Message"]</div> }
        @RenderBody()
    </div>
</body>
</html>

藍色加粗部分是我們的后台樣式,具體代碼如下;紅色加粗部分引入的JS是為了驗證客戶端數據;粉紅色加粗部分則是一個提示信息的預留位置。

后台樣式我們在web項目的Content文件下創建,具體樣式如下:

BODY, TD { font-family: Segoe UI, Verdana }
H1 { padding: .5em; padding-top: 0; font-weight: bold; 
     font-size: 1.5em; border-bottom: 2px solid gray; }
DIV#content { padding: .9em; }
TABLE.Grid TD, TABLE.Grid TH { border-bottom: 1px dotted gray; text-align:left; }
TABLE.Grid { border-collapse: collapse; width:100%; } 
TABLE.Grid TH.NumericCol, Table.Grid TD.NumericCol {
    text-align: right; padding-right: 1em; }
FORM {margin-bottom: 0px;   } 
DIV.Message { background: gray; color:White; padding: .2em; margin-top:.25em; } 

.field-validation-error { color: red; display: block; }
.field-validation-valid { display: none; }
.input-validation-error { border: 1px solid red; background-color: #ffeeee; }
.validation-summary-errors { font-weight: bold; color: red; }
.validation-summary-valid { display: none; }

.editor-field { margin-bottom: .8em; }
.editor-label { font-weight: bold; }
.editor-label:after { content: ":" }
.text-box { width: 25em; }
.multi-line { height: 5em; font-family: Segoe UI, Verdana; }

OK!現在回到我們的AdminController里面來,創建我們的List展示頁面,具體如下圖4.

圖4.建立好Index.cshtml頁面,修改它的代碼如下:

@model IEnumerable<SportsStore.Domain.Entities.Product>

@{
    ViewBag.Title = "Administration All Index";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h1>Administration All Index</h1>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="Grid">
    <tr>
        <th>ID</th> 
        <th>Name</th>  
        <th class="NumericCol">Price</th> 
        <th>Actions</th> 
    </tr>
    @foreach (var item in Model)
    {
    <tr>
        <td>@item.ProductID</td>
        <td>@Html.ActionLink(item.Name, "Edit", new { item.ProductID })</td> 
        <td class="NumericCol">@item.Price.ToString("c")</td> 
        <td>
        @using (Html.BeginForm("Delete", "Admin"))
        {
          @Html.Hidden("ProductID", item.ProductID)  
            <input type="submit" value="Delete"/>
        }
        </td> 
    </tr>
    }
</table>
<p>@Html.ActionLink("Add a New Product","Create")</p>

寫完這個我們運行一下我們的項目,結果如下圖5.(因為這個跟前台沒有直接關聯,所以寫完需要我們拼寫它的路徑也就是你想看頁面的Controller/Index的URL方式)。

圖5.這個后台一個簡單的展示頁面,他現在只具備列出我們所有商品,像新建,編輯,刪除的功能還不存在。接下來一並搞這個三個功能,都是在我們的AdminController控制器里完成,首先來看編輯和新建功能。

一個編輯功能應該是管理者可以修改商品的屬性(信息)等,接下來我們在AdminController添加一個編輯功能,具體代碼如下:

        /// <summary>
        /// 編輯方法
        /// </summary>
        /// <param name="productId">商品的ID</param>
        /// <returns>編輯后的商品</returns>
        public ViewResult Edit(int productId)
        {
            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            return this.View(product);
        }

接着我們創建Edit Action(方法)對應的視圖頁面,具體如下圖6(我們在這里還繼續使用強類型數據模型).

圖6.創建完Edit.cshtml后,我們修改他如下:

@model SportsStore.Domain.Entities.Product

@{
    ViewBag.Title = "Admin:Edit" + @Model.Name;
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Admin Edit @Model.Name</h1>
@using (Html.BeginForm())
{
    @Html.EditorForModel() <input type="submit" value="Save" />
    @Html.ActionLink("Cancel And Return To List", "Index")
}

上面紅色加粗部分@Html.EditorForModel()是一個復制方法,MVC框架會自動檢測創建編輯窗口,運行可以看到效果如下圖7.

圖7.我們一般習慣在編輯的時候,不讓編輯ProductID這個屬性,還有我們的描述相比其他的字體應該更小點。我們可以在這里試着用一下"模型元數據"(model metadata)這個后面在做講解,修改我們Product的實體類如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace SportsStore.Domain.Entities
{
    public class Product : Object
    {
        [HiddenInput(DisplayValue = false)] public int ProductID { get; set; }

        public string Name { get; set; }

        [DataType(DataType.MultilineText)] public string Description { get; set; }

        public decimal Price { get; set; }

        public string Category { get; set; }
    }
}

 在MVC框架里HiddenInput會是呈現的屬性隱藏起來,DataType給定我們一個值允許我們執行相應的編輯。添加玩屬性后在運行我們的項目如下圖8.

圖8.我們之前編輯的商品信息,怎么保存到儲存卡呢!我們需要在IProductRepository接口添加保存的方法,這是在需要保存的地方調用方法即可;所以我們修改IProductRepository接口如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Abstract
{
    public interface IProductRepository
    {
        IQueryable<Product> Products { get; }

        //保存商品
        void SaveProduct(Product product);
    }
}

接着我們需要在EFProductRepository類里實現他,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Abstract;
using System.Data.Entity;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Concrete
{
    public class EFProductRepository : IProductRepository
    {

        private EFDbContext context = new EFDbContext();
        public IQueryable<Product> Products
        {
            get { return this.context.Products; }
        }
        //實現接口里保存商品的方法
        public void SaveProduct(Product product) 
        {
            //不存在商品就新增
            if (product.ProductID == 0)
            {
                this.context.Products.Add(product);
            }
            this.context.SaveChanges();
        }

    }

    //EFDbContext類可以使簡單數據模型與數據庫交互
    public class EFDbContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    }
}

接下來我們實現Edit Action(方法)的Post提交處理,具體代碼如下:

        [HttpPost]
        public ActionResult Edit(Product product)
        {
            if (ModelState.IsValid)
            {
                this.repository.SaveProduct(product);
                //設置臨時字典
                TempData["message"] = string.Format("{0} Has Been Saved", product.Name);
                return this.View(product);
                    //.RedirectToAction("Index");
           }
        } 

我們檢查模型綁定器已經能夠驗證用戶提交的數據。如果一切OK,我們就可以保存到儲存庫里面。

然后我們更新一下一條信息看看效果,運行如下圖9.

圖9.因為在這里我們建立的模版里留着提示消息的位置,使用TempData來顯示消息,TempData會自動獲取傳遞的字典數據,而且他會自動銷毀數據,我們只要從新刷新頁面他就會銷毀當前傳遞的數據。

接下來我們需要添加模型驗證,就目前而言,我們編輯的時候,價格可以輸入負值,商品描述為空等都可以保存,而這些是不允許,所以我們需要給我們的商品模型添加驗證屬性,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace SportsStore.Domain.Entities
{
    public class Product : Object
    {
        [HiddenInput(DisplayValue = false)]
        public int ProductID { get; set; }

        [Required(ErrorMessage = "Please enter a product name")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Please enter a description")]
        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        [Required]
        [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
        public decimal Price { get; set; }

        [Required(ErrorMessage = "Please specify a category")]
        public string Category { get; set; }

        public byte[] ImageData { get; set; }

        [HiddenInput(DisplayValue = false)]
        public string ImageMimeType { get; set; }
    }
}

添加驗證特性后,我們運行項目如果輸入錯誤的話,會有相應的提示,如下圖10.

圖10.

然后我們實現新建商品功能,在AdminController里添加Create Action(方法),具體代碼如下:

        /// <summary>
        /// 創建商品
        /// </summary>
        /// <returns>新的商品</returns>
        public ViewResult Create()
        {
            return this.View("Edit", new Product());
        }

我們這里沒有返回默認視圖,而是指定到Edit Action(方法),我們試着顯示指定在別的Controller控制器和Action方法來搞搞。修改我們的編輯(Edit.cshtml)頁面如下:

@model SportsStore.Domain.Entities.Product

@{
    ViewBag.Title = "Admin:Edit" + @Model.Name;
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Admin Edit @Model.Name</h1>
@using (Html.BeginForm("Edit", "Admin"))
{
    @Html.EditorForModel()
    <input type="submit" value="Save" />
    @Html.ActionLink("Cancel And Return To List", "Index")
}

試着運行我們的項目如下圖10。

圖10我們新建的商品信息,然后接續我們的刪除操作。和保存一樣我們在IProductRepository接口里定義刪除的方法如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Abstract
{
    public interface IProductRepository
    {
        IQueryable<Product> Products { get; }

        //保存商品
        void SaveProduct(Product product);

        //刪除商品
        void DeleteProduct(Product product);
    }
}

接着我們在EFProductRepository類里實現上面定義的刪除方法,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Abstract;
using System.Data.Entity;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Concrete
{
    public class EFProductRepository : IProductRepository
    {

        private EFDbContext context = new EFDbContext();
        public IQueryable<Product> Products
        {
            get { return this.context.Products; }
        }
        //實現接口里保存商品的方法
        public void SaveProduct(Product product) 
        {
            //不存在商品就新增
            if (product.ProductID == 0)
            {
                this.context.Products.Add(product);
            }
            this.context.SaveChanges();
        }
        //實現接口的刪除商品的方法
        public void DeleteProduct(Product product) 
        {
            this.context.Products.Remove(product);
            this.context.SaveChanges();
        }
    }

    //EFDbContext類可以使簡單數據模型與數據庫交互
    public class EFDbContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    }
}

然后繼續在AdminController里添加我們的刪除功能,具體代碼如下:

        /// <summary>
        /// 刪除商品
        /// </summary>
        /// <param name="productID">商品的ID</param>
        /// <returns>URL從新指向列表</returns>
        [HttpPost]
        public ActionResult Delete(int productId)
        {
            Product prod = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            if (prod!=null)
            {
                this.repository.DeleteProduct(prod);
                TempData["message"] = string.Format("{0} Was Deleted", prod.Name);
            }
            return this.RedirectToAction("Index");
        }

搞完刪除運行一下我們的項目,試試刪除功能,具體如下圖11.

圖11.(刪除了ID為15的信息)我們的后台應該有一個簡單的登錄頁面,做也要做個樣子嗎?簡單的搞搞我們只要說明那么回事。Asp.Net MVC是建立在Asp.Net核心平台上的,所以我們可以訪問Asp.Net Form驗證的功能,這也是一個比較通用的功能。只有登錄成功的人才能操作后台。關於From驗證我們配置我們項目的Web.Config如下:

......
 <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880">
        <credentials passwordFormat="Clear">
          <user name="admin" password="123" />
        </credentials>
      </forms>
</authentication>
.......

MVC框架有一個非常強大的功能稱為Filters。這些都是Attributes,應用到一個Action方法或Controller類。當一個請求被處理的時候,這些Attributes引入了額外的邏輯。我們也可以定義自己的Filter。接下來給我們AdminController添加Filters(過濾器吧)!具體操作如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;

namespace SportsStore.WebUI.Controllers
{
    [Authorize] public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
.......   

添加了Filters(過濾器),然后我們在運行項目,結果如下圖12.

圖12.這就是我們使用Filters(過濾器)的結果。接下來我們需要一個驗證者(程序),我們首先定義,身份驗證提供者接口,在我們Web項目的Infrastructure/Abstract文件夾下創建接口("IAuthProvider"),具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SportsStore.WebUI.Infrastructure.Abstract
{
    public interface IAuthProvider
    {
        bool Authenticate(string username, string password);
    }
}

接着在Infrastructure文件夾里面再創建一個Concrete文件夾,添加一個實現類FormsAuthProvider,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SportsStore.WebUI.Infrastructure.Abstract;
using System.Web.Security;

namespace SportsStore.WebUI.Infrastructure.Concrete
{
    public class FormsAuthProvider : IAuthProvider
    {
        public bool Authenticate(string username, string password) 
        {
            bool result = FormsAuthentication.Authenticate(username, password);
            if (result)
            {
                FormsAuthentication.SetAuthCookie(username, false);
            }
            return result;
        }
    }
}

然后在NinjectControllerFactory里面使用Ninject綁定,具體代碼如下:

        private void AddBindings()
        {
            //綁定額外數據
            this.ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();

            EmailSettings emailSettings = new EmailSettings
            {
                WriteAsFile = bool.Parse(ConfigurationManager.AppSettings["Email.WriteAsFile"] ?? "false")
            };
            this.ninjectKernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>()
                                                      .WithConstructorArgument("settings", emailSettings);
            //添加身份驗證 this.ninjectKernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
        }

然后我們需要創建一個登錄的視圖模型類("LogOnViewModel")為了傳遞數據,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace SportsStore.WebUI.Models
{
    public class LogOnViewModel
    {
        [Required]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }
}

然后在項目添加AccountController控制器類,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.WebUI.Infrastructure.Abstract;
using SportsStore.WebUI.Models;

namespace SportsStore.WebUI.Controllers
{
    public class AccountController : Controller
    {
        IAuthProvider authProvider;
        public AccountController(IAuthProvider auth) 
        {
            this.authProvider = auth;
        }
        /// <summary>
        /// 登錄頁面
        /// </summary>
        /// <returns>View</returns>
        public ViewResult LogOn() 
        {
            return this.View();
        }
        /// <summary>
        /// Post請求登錄頁面
        /// </summary>
        [HttpPost]
        public ActionResult LogOn(LogOnViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (this.authProvider.Authenticate(model.UserName, model.Password))
                {
                    return this.Redirect(returnUrl ?? Url.Action("Index", "Admin"));
                }
                else
                {
                    ModelState.AddModelError("", "Incorrect username or password");
                    return this.View();
                }
            }
            else 
            {
                return this.View(); 
            }
        }
    }
}

接着,我們創建LogOn的視圖,如下圖13.

圖13.創建好LogOn.cshtml頁面后,具體代碼如下:

@model SportsStore.WebUI.Models.LogOnViewModel

@{
    ViewBag.Title = "Admin:LogOn";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h1>Log In</h1>
<p>Please log in to access the administrative area:</p>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    @Html.EditorForModel()
    <p><input type="submit" value="Log In" /></p>
}

添加好我們的登錄頁面,運行程序如下圖14.

圖16.(這里只有輸入我們在Web.comfig文件里配置的帳號密碼方可登錄進去)。接下來搞我們最后一個功能圖片上傳功能。首先我們必須給我們的數據表里面添加新的字段,具體如下圖17.

圖17.更改數據表,我們也要同步到我們的域模型,修改我們的Product模型如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace SportsStore.Domain.Entities
{
    public class Product : Object
    {
        [HiddenInput(DisplayValue = false)]
        public int ProductID { get; set; }

        [Required(ErrorMessage = "Please enter a product name")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Please enter a description")]
        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        [Required]
        [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
        public decimal Price { get; set; }

        [Required(ErrorMessage = "Please specify a category")]
        public string Category { get; set; }

        public byte[] ImageData { get; set; }

        [HiddenInput(DisplayValue = false)]
        public string ImageMimeType { get; set; }
    }
}

然后我們需要跟新到我們的實體模型,如給你給項目添加了數據模型,打開運行"自定義功能",VS就會自動幫你同步的,我這沒有用數據模型的(*.edmx),所以我這里只需要更新域模型即可。創建用戶的上傳界面,上傳圖片習慣應該在編輯頁面,所以修改我們的Edit.cshtml頁面,代碼如下:

@model SportsStore.Domain.Entities.Product

@{
    ViewBag.Title = "Admin:Edit" + @Model.Name;
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Admin Edit @Model.Name</h1>
@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.EditorForModel()
    <div class="editor-label">Image</div> <div class="editor-field"> @if (Model.ImageData == null) { @:None } else { <img width="150" height="150" src="@Url.Action("GetImage", "Product", new { Model.ProductID })" /> } <div>Upload new image:<input type="file" name="Image" /></div> </div>
    <input type="submit" value="Save" />
    @Html.ActionLink("Cancel And Return To List", "Index")
}

接下來我們需要在AdminController的Edit Action(方法)保存我們的圖片數據,具體修改如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;

namespace SportsStore.WebUI.Controllers
{
    [Authorize]
    public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
        /// <summary>
        /// 展示商品列表頁面
        /// </summary>
        /// <returns>商品的列表</returns>
        public ViewResult Index()
        {
            return this.View(this.repository.Products);
        }
        /// <summary>
        /// 編輯方法
        /// </summary>
        /// <param name="productId">商品的ID</param>
        /// <returns>編輯后的商品</returns>
        public ViewResult Edit(int productId)
        {
            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            return this.View(product);
        }
        [HttpPost]
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
            if (ModelState.IsValid)
            {
                if (image != null) { product.ImageMimeType = image.ContentType; product.ImageData = new byte[image.ContentLength]; image.InputStream.Read(product.ImageData, 0, image.ContentLength); } this.repository.SaveProduct(product);
                //設置臨時字典
                TempData["message"] = string.Format("{0} Has Been Saved", product.Name);
                return this.View(product);
                    //.RedirectToAction("Index");
            }
        }
        /// <summary>
        /// 創建商品
        /// </summary>
        /// <returns>新的商品</returns>
        public ViewResult Create()
        {
            return this.View("Edit", new Product());
        }
        /// <summary>
        /// 刪除商品
        /// </summary>
        /// <param name="productID">商品的ID</param>
        /// <returns>URL從新指向列表</returns>
        [HttpPost]
        public ActionResult Delete(int productId)
        {
            Product prod = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            if (prod!=null)
            {
                this.repository.DeleteProduct(prod);
                TempData["message"] = string.Format("{0} Was Deleted", prod.Name);
            }
            return this.RedirectToAction("Index");
        }
    }
}

OK,我們貌似還需要一個取出存貯圖片的方法,在我們的ProductOntroller里添加GetImage Action(方法),具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Concrete;
using SportsStore.WebUI.Models;
using SportsStore.Domain.Entities;

namespace SportsStore.WebUI.Controllers
{
    public class ProductController : Controller
    {
        public int PageSize = 4; //設置一頁顯示多少商品
        private IProductRepository repository;
        public ProductController(IProductRepository productReposittory) 
        {
            this.repository = productReposittory;
        }
        //返回一個視圖
        public ViewResult List(string category, int page = 1)
        {
            ProductsListViewModel viewModel = new ProductsListViewModel
            {
                Products = this.repository.Products
                                                .Where(h => category == null || h.Category == category)
                                                .OrderBy(h => h.ProductID)
                                                .Skip((page - 1) * PageSize)
                                                .Take(PageSize),
                PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = PageSize,
                    TotalItems = category == null ? this.repository.Products.Count() :
                    this.repository.Products.Where(h => h.Category == category).Count()
                },
                CurrentCategory = category
            };
            return this.View(viewModel);
        }
        //獲取圖片的方法 public FileContentResult GetImage(int productId) { Product prod = this.repository.Products.FirstOrDefault(h => h.ProductID == productId); if (prod != null) { return File(prod.ImageData, prod.ImageMimeType); } else { return null; } }
    }
}

還記得我們在("EFProductRepository")實現保存方法的時候,我們只考慮到不存在商品的情況,也就是我們實際上就無法修改商品,現在我們在實現他商品存在修改的情況,具體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Abstract;
using System.Data.Entity;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Concrete
{
    public class EFProductRepository : IProductRepository
    {

        private EFDbContext context = new EFDbContext();
        public IQueryable<Product> Products
        {
            get { return this.context.Products; }
        }
        //實現接口里保存商品的方法
        public void SaveProduct(Product product) 
        {
            //不存在商品就新增
            if (product.ProductID == 0)
            {
                this.context.Products.Add(product);
            }
            else { //存在則修改 this.context.Products.Attach(product); //EntityFramwork4.0修改的寫法 //this.context.ObjectStateManager.ChangeObjectState(product, System.Data.EntityState.Modified); //EntityFramwork4.1修改的寫法 this.context.Entry(product).State = System.Data.EntityState.Modified; } this.context.SaveChanges();
        }
        //實現接口的刪除商品的方法
        public void DeleteProduct(Product product) 
        {
            this.context.Products.Remove(product);
            this.context.SaveChanges();
        }
    }

    //EFDbContext類可以使簡單數據模型與數據庫交互
    public class EFDbContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    }
}

然后運行一下我們的Web程序,看看我們的上傳功能到時是否OK。運行結果如下圖18.

圖17.OK說明我們的上傳已經是沒有問題的了!我們在后台上傳圖片前台肯定也需要一塊地方展示商品圖片,還還記我們的前台展示商品列表的頁面好像用的是一個局部視圖,那么我們就在這塊局部視圖中給商品圖片分配一塊位置,修改ProductSummary.cshtml頁面,具體如下:

@model SportsStore.Domain.Entities.Product

@{
    ViewBag.Title = "ProductSummary";
}

<div class="item">
@if (Model.ImageData != null)
{
<div style="float:left;margin-right:20px">
<img width="75" height="75" src="@Url.Action("GetImage", "Product", new { Model.ProductID })" />
</div>
}
<h3>@Model.Name</h3>
@Model.Description
@using (Html.BeginForm("AddToCart","Cart"))
{
    @Html.HiddenFor(h=>h.ProductID)
    @Html.Hidden("returnUrl",this.Request.Url.PathAndQuery)
    <input type="submit" value="+ Add to cart" />
}
<h4>@Model.Price.ToString("C")</h4>
</div>

在前台分配好商品展示的地方,在后台上傳好商品的圖片然后運行,前台頁面,運行結果如下圖18.

圖18.今天的后台就實戰到這里,我的簡單的購物流程也就暫時搞一個階段了,后續我們在繼續深入的學習MVC,幾天的這篇文章寫的真的很倉促,要是那里有寫錯還是描述錯誤的地方,還請各位前輩朋友多多批評指導,大家共同進步啊!在此,深表明哥指導學習。

源碼包-->下載(這里稍后在放上)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM