1. 程式人生 > >ASP.net Mvc SportsSpore專案開發(四)

ASP.net Mvc SportsSpore專案開發(四)

1.使用模型繫結

MVC框架使用了一個叫做“模型繫結”的系統,以便通過HTTP請求來建立一些C#物件,目的是將它們作為引數值傳遞給動作方法。這是MVC 處理表單的方式。例如,框架會考查目標動作方法的引數,用一個模型繫結器來獲取由瀏覽器傳送過來的表單值,並在傳遞給動作方法之前將它們轉換成同名引數的型別。

模型繫結器能夠通過請求中可用的各種資訊來建立C#型別,這是MVC框架的核心特性之一。本節將建立一個自定義的模型繫結器來改善CartController類。

建立自定義模型繫結器

在SportsStore.WebUI專案中新增一個新的資料夾,名稱為Infrastructure/Binders,並在其中建立一個CartModelBinder.cs類檔案。

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

namespace SportsStore.WebUI.Infrastructure.Binders
{
    public class CartModelBinder : IModelBinder
    {
        private const string sessionKey = "Cart";
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            //通過會話獲取Cart
            Cart cart = null;
            if (controllerContext.HttpContext.Session != null)
            {
                cart = (Cart)controllerContext.HttpContext.Session[sessionKey];
            }
            //若會話中沒有Cart,則建立一個
            if(cart == null)
            {
                cart = new Cart();
                if (controllerContext.HttpContext.Session != null)
                {
                    controllerContext.HttpContext.Session[sessionKey] = cart;
                }
            }
            //返回cart
            return cart;
        }
    }
}

IModelBinder介面定義了一個方法:BindModel,為其提供的兩個引數能夠用來建立域模型物件。通過ControllerContext能夠訪問控制器類所具有的全部資訊,包括客戶端請求的細節;ModelBindingContext能夠提供的資訊包括:要求你建立的模型物件以及使繫結過程更易於處理的工具。

ControllerContext類,具有HTTPContext屬性,HTTPContext又相應地有一個Session屬性,該屬效能夠獲取和設定會話資料。通過讀取會話資料的鍵值,可以獲取與使用者會話關聯的Cart物件,並在沒有會話時建立一個Cart物件。

下面需要設定,告訴MVC框架,它可以使用CartModelBinder類建立Cart例項。這需要在Global.asax的Application_Start方法中進行設定,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using SportsStore.Domain.Entities;
using SportsStore.WebUI.Infrastructure.Binders;

namespace SportsStore.WebUI
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
        }
    }
}

下面更新CartController類,刪去GetCart方法,並依靠模型繫結器為控制器提供 Cart物件。

public ViewResult Index(Cart cart,string returnUrl)
        {
            return View(new CartIndexViewModel
            {
                //Cart = GetCart(),
                ReturnUrl = returnUrl,
                Cart = cart
            });
        }

        public RedirectToRouteResult AddToCart(Cart cart, int productId,string returnUrl)
        {
            Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
            if (product != null)
            {
                cart.AddItem(product, 1);
                //GetCart().AddItem(product, 1);
            }
            return RedirectToAction("Index", new { returnUrl });
        }

        public RedirectToRouteResult RemoveFromCart(Cart cart, int productId,string returnUrl)
        {
            Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
            if (product != null)
            {
                cart.RemoveLine(product);
                //GetCart().RemoveLine(product);
            }
            return RedirectToAction("Index", new { returnUrl });
        }

當MVC框架接收到一個請求,比如,要求呼叫AddToCart方法時,會首先考查動作方法的引數,然後考查可用的繫結器列表,並嘗試找到一個能夠為各個引數型別建立例項的繫結器。於是會要求自定義繫結器建立Cart物件,而這是通過使用會話狀態特性來完成的。通過自定義繫結器和預設繫結器,MVC框架能夠建立一組呼叫動作方法所需要的引數,這讓開發者能夠重構控制器,以便在接收到請求時,控制器不必知道如何建立Cart物件。

像這樣使用自定義模型繫結器有幾個好處:第一個好處是把用來建立Cart物件與建立控制器的邏輯分離開來了,這讓開發者能夠修改儲存cart物件的方式,而不需要修改控制器;第二個好處是任何使用Cart物件的控制器類,都能夠簡單地把這些物件宣告為動作方法引數,並能夠自定義模型繫結器;第三個好處,是它能夠對Cart控制器進行單元測試,而不需要模仿大量的ASP.net通道。

2.完成購物車功能

刪除購物車物品

前面定義時已經在控制器中定義了RemoveFromCart動作方法,因此,讓客戶刪除物品只不過是在檢視中將這個方法顯示出來而已。在購物車物品的每一行中新增一個Remove刪除按鈕。對Views/Cart/Index.cshtml檔案做修改

<tbody>
        @foreach(var line in Model.Cart.Lines)
        {
            <tr>
                <td class="text-center">@line.Quantity</td>
                <td class="text-center">@line.Product.Name</td>
                <td class="text-center">@line.Product.Price.ToString("c")</td>
                <td class="text-center">@((line.Quantity*line.Product.Price).ToString("c"))</td>
                <td>
                    @using (Html.BeginForm("RemoveFromCart", "Cart"))
                    {
                        @Html.Hidden("ProductId",line.Product.ProductID)
                        @Html.HiddenFor(x=>x.ReturnUrl)
                        <input class="btn btn-sm btn-warning"
                               type="submit" value="Remove"/>
                    }
                </td>
            </tr>
        }
    </tbody>

使用強型別的Html.HidderFor輔助器方法,為ReturnURL模型屬性建立一個隱藏欄位,但這需要使用基於字串的Html.Hidden輔助器方法,對ProductID欄位做同樣的事。如果寫成Html.HidderFor(x=>x.line.Product.ProductID),該輔助器方法便會渲染一個以line.Product.ProductID為名稱的隱藏欄位。該欄位名與CartController.RemoveFromCart動作方法的引數名不匹配,這會使預設的模型繫結器無法工作,因此,MVC框架便不能呼叫此方法了。


3.新增購物車摘要

為了讓使用者知道自己購物車中都有什麼,我們在導航欄上新增一個動作,用來獲取物品的數量及總價格,和跳轉的連結。

在CartControllers檔案中新增Summary方法

 public PartialViewResult Summary(Cart cart)
        {
            return PartialView(cart);
        }

右擊Summary新增相應檢視

@model SportsStore.Domain.Entities.Cart

<div class="navbar-right">
    @Html.ActionLink("Checkout", "Index", "Cart", new { returnUrl = Request.Url.PathAndQuery }, new {@class = "btn btn-default navbar-btn"})
</div>

<div class="navbar-text navbar-right">
    <b>我的購物車:</b>
    @Model.Lines.Sum(x=>x.Quantity) 個物品@*item(s)*@,
    <b>總價格:</b>
    @Model.ComputeTotalValue().ToString("c")
</div>

在_Layout.cshtml檔案中呼叫Summary動作方法,以顯示購物車摘要

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />

    <title>@ViewBag.Title</title>
    <link href="~/Content/bootstrap.css" rel="stylesheet"/>
    <link href="~/Content/bootstrap-theme.css" rel="stylesheet" />
    <link href="~/Content/ErrorStyles.css" rel="stylesheet"/>
</head>
<body>
    <div class="navbar navbar-inverse" role="navigation">
        <a class="navbar-brand" href="#">Sports Store</a>
        @Html.Action("Summary","Cart")
    </div>
    <div class="row panel">
        <div id="categories"class="col-xs-3">
            @Html.Action("Menu", "Nav")
        </div>
        <div class="col-xs-8">
            @RenderBody()
        </div>
    </div>
    
</body>
</html>

4.遞交訂單

在SportsStore.Domain的Entities檔案下新增一個ShippingDetails的類檔案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;

namespace SportsStore.Domain.Entities
{
    public class ShippingDetails
    {
        [Required(ErrorMessage ="請選擇一個產品名稱")]
        public string Name { get; set; }
        [Required(ErrorMessage ="請輸入第一個位址列")]
        [Display(Name="位址列1")]
        public string Line1 { get; set; }
        [Display(Name = "位址列2")]
        public string Line2 { get; set; }
        [Display(Name = "位址列3")]
        public string Line3 { get; set; }
        [Required(ErrorMessage ="請選擇一個城市名稱")]
        [Display(Name = "省")]
        public string City { get; set; }

        [Required(ErrorMessage ="請選擇一個縣")]
        [Display(Name = "市")]
        public string State { get; set; }
        [Display(Name = "縣")]
        public string Zip { get; set; }
        [Required(ErrorMessage ="請選擇一個國家名")]
        [Display(Name = "國家")]
        public string Country { get; set; }
        public bool GiftWrap { get; set; }
    }
}

新增上驗證以及展示名。

新增結算過程

在Index檢視頁,新增立即結算按鈕

<div class="text-center">
    <a class="btn btn-primary" href="@Model.ReturnUrl">繼續購物</a>
    @Html.ActionLink("立即結算", "Checkout", null, new { @class = "btn btn-primary"})
</div>

然後在CartController中定義Checkout方法

public ViewResult Checkout(Cart cart,ShippingDetails ship)
        {
           return View(new ShippingDetails());
        }

建立Checkout檢視

@model SportsStore.Domain.Entities.ShippingDetails

@{
    ViewBag.Title = "SportsStore:Checkout";
}

<h2>立即結算</h2>
<p>請進入你的購物清單,我們會立刻清點你的商品</p>

@using (Html.BeginForm())
{
    @Html.ValidationSummary()
    <h3>物品結算</h3>
    <div class="form-group">
        <label>姓名:</label>
        @Html.TextBoxFor(x => x.Name, new { @class = "form-control" })
    </div>

    <h3>地址</h3>
    foreach (var property in ViewData.ModelMetadata.Properties)
    {
        if (property.PropertyName != "Name" && property.PropertyName != "GiftWrap")
        {
            <div class="form-group">
                <label>@(property.DisplayName??property.PropertyName)</label>
                @Html.TextBox(property.PropertyName, null, new { @class="form-control"})
            </div>
        }
    }

    <h3>選項</h3>
    <div class="checkbox">
        <label>
            @Html.EditorFor(x => x.GiftWrap)
            打包這些物品
        </label>
    </div>

    <div class="text-center">
        <input class="btn btn-primary" type="submit" value="完成結算" />
    </div>

靜態的ViewData.ModelMetadata屬性返回的是一個System.Web.Mvc.ModelMetaData物件,該物件提供了檢視的模型型別資訊。在foreach迴圈中所使用的Properties屬性返回的是一個ModelMetadata物件的集合,Properties中的每一個都代表了模型型別所定義的屬性。這裡使用PropertyName屬性,以確保不為Name或GiftWrap屬性生成內容(這兩者的內容在檢視的其他地方處理),並且為其他所有屬性生成了一組元素,這些元素都帶有Bootstrap的class。

其中for和if關鍵字位於Razor表示式的範圍之內,故不需要以@符號作為字首。

5.實現訂單處理器

應用程式還需要一個元件,以便能夠對訂單的細節進行處理。為了與MVC模型原理保持一致,打算為此功能定義一個介面、編寫該介面的一個實現介面,然後用DI容器(Ninject)將兩者關聯起來。

在SportsStore.Domain的Abstract檔案下新增一個介面IOrderProcessor

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

namespace SportsStore.Domain.Abstract
{
    public interface IOrderProcessor
    {
        void ProcessOrder(Cart cart, ShippingDetails shippingDetails);
    }
}

在SportsStore.Domain專案的Concrete檔案下新增一個類檔案,名為EmailOrderProcessor

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using System.Net;
using System.Net.Mail;

namespace SportsStore.Domain.Concrete
{
    public class EmailOrderProcessor : IOrderProcessor
    {//使用了包含在.Net框架中內建的SMTP(簡單郵件傳輸協議)
        private EmailSettings emailSettings;

        public EmailOrderProcessor(EmailSettings settings)
        {
            emailSettings = settings;
        }
        public void ProcessOrder(Cart cart, ShippingDetails shippingDetails)
        {
            using(var smtpClient = new SmtpClient())
            {
                smtpClient.EnableSsl = emailSettings.UseSsl;
                smtpClient.Host = emailSettings.ServerName;
                smtpClient.Port = emailSettings.ServerPort;
                smtpClient.UseDefaultCredentials = false;
                smtpClient.Credentials = new NetworkCredential(emailSettings.Username, emailSettings.Password);

                if (emailSettings.WriteAsFile)
                {
                    smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
                    smtpClient.PickupDirectoryLocation = emailSettings.FileLocation;
                    smtpClient.EnableSsl = false;
                }

                StringBuilder body = new StringBuilder().AppendLine("一個新的命令提交了").AppendLine("- - -").AppendLine("物品:");
                foreach (var line in cart.Lines)
                {
                    var subtotal = line.Product.Price * line.Quantity;
                    body.AppendFormat("{0}*{1}(subtotal:{2:c}", line.Quantity, line.Product.Name, subtotal);
                }

                body.AppendFormat("Total order value:{0:c}", cart.ComputeTotalValue()).AppendLine("- - -").AppendLine("Ship to:").AppendLine(shippingDetails.Name)
                    .AppendLine(shippingDetails.Line1).AppendLine(shippingDetails.Line2 ?? "").AppendLine(shippingDetails.Line3 ?? "")
                    .AppendLine(shippingDetails.City).AppendLine(shippingDetails.State ?? "").AppendLine(shippingDetails.Country).AppendLine(shippingDetails.Zip)
                    .AppendLine("- - - ").AppendFormat("Gift wrap:{0}", shippingDetails.GiftWrap ? "Yes" : "No");
                MailMessage mailMessage = new MailMessage(
                    emailSettings.MailFromAddress,//From
                    emailSettings.MailToAddress,
                    "新的命令已提交!",
                    body.ToString());
                if (emailSettings.WriteAsFile)
                {
                    mailMessage.BodyEncoding = Encoding.ASCII;
                }
                smtpClient.Send(mailMessage);
            }

        }
    }

    public class EmailSettings
    {
        public string MailToAddress = "[email protected]";
        public string MailFromAddress = "[email protected]";
        public bool UseSsl = true;
        public string Username = "MySmtpUsername";
        public string Password = "MySmtpPassword";
        public string ServerName = "smtp.example.com";
        public int ServerPort = 587;
        public bool WriteAsFile = false;
        public string FileLocation = @"d:\sports_store_emails";
    }

}

現在IOrderProcessor介面有了一個實現,也有了配置它的手段,於是可以用Ninject建立它的例項。在SportsStore.WebUI專案Infrastructure資料夾中,編輯NinjectDependencyResolver檔案,對其中的Addbindings方法進行修改:

private void AddBindings()
        {//繫結
            //Mock<IProductsRepository> mock = new Mock<IProductsRepository>();
            //mock.Setup(m => m.Products).Returns(new List<Product> {
            //    new Product {Name="Football",Price = 25 },
            //    new Product {Name="Surf board",Price = 179 },
            //    new Product {Name="Running shoes",Price = 95 }
            //});
            //kernel.Bind<IProductsRepository>().ToConstant(mock.Object);
            kernel.Bind<IProductsRepository>().To<EFProductRepository>();

            EmailSettings emailSettings = new EmailSettings
            {
                WriteAsFile = bool.Parse(ConfigurationManager.AppSettings["Email.WriteAsFile"] ?? "false")
            };
            kernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>().WithConstructorArgument("settings", emailSettings);
        }

在Web.config檔案中配置Email的連結。

 <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="Email.WriteAsFile" value="true"/>
  </appSettings>

完成購物車控制器,修改CartController類,

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

namespace SportsStore.WebUI.Controllers
{
    public class CartController : Controller
    {
        private IProductsRepository repository;
        private IOrderProcessor orderProcessor;

        public CartController(IProductsRepository repo,IOrderProcessor proc)
        {
            repository = repo;
            orderProcessor = proc;
        }

        public ViewResult Index(Cart cart,string returnUrl)
        {
            return View(new CartIndexViewModel
            {
                //Cart = GetCart(),
                ReturnUrl = returnUrl,
                Cart = cart
            });
        }

        public RedirectToRouteResult AddToCart(Cart cart, int productId,string returnUrl)
        {
            Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
            if (product != null)
            {
                cart.AddItem(product, 1);
                //GetCart().AddItem(product, 1);
            }
            return RedirectToAction("Index", new { returnUrl });
        }

        public RedirectToRouteResult RemoveFromCart(Cart cart, int productId,string returnUrl)
        {
            Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
            if (product != null)
            {
                cart.RemoveLine(product);
                //GetCart().RemoveLine(product);
            }
            return RedirectToAction("Index", new { returnUrl });
        }

        public PartialViewResult Summary(Cart cart)
        {
            return PartialView(cart);
        }
        public ViewResult Checkout(Cart cart,ShippingDetails ship)
        {
            if(cart.Lines.Count() == 0)
            {
                ModelState.AddModelError("", "抱歉,你的購物車是空的!");
            }
            if (ModelState.IsValid)
            {
                orderProcessor.ProcessOrder(cart, ship);
                cart.Clear();
                return View("Completed");
            }
            else
            {
                return View(ship);
            }
            //return View(new ShippingDetails());
        }
        //Asp.net 有一個很好的會話特性,使用重寫cookie或URL的辦法,將一個使用者的多個請求關聯在一起,形成一個單一的會話。
    }
}

建立一些CSS樣式,用於驗證摘要所使用的那些class以及MVC框架新增的那些非法元素,在Content檔案下新建立一個樣式表ErrorStyles.css

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

顯示致謝頁面

在View\Cart檔案下建立一個新的檢視Completed.cshtml

@{
    ViewBag.Title = "SportsStore:Order Submitted";
}

<h2>Thanks!</h2>
Thanks for placing your order. We'll ship your goods as soon as possible.

相關推薦

ASP.net Mvc SportsSpore專案開發(

1.使用模型繫結MVC框架使用了一個叫做“模型繫結”的系統,以便通過HTTP請求來建立一些C#物件,目的是將它們作為引數值傳遞給動作方法。這是MVC 處理表單的方式。例如,框架會考查目標動作方法的引數,用一個模型繫結器來獲取由瀏覽器傳送過來的表單值,並在傳遞給動作方法之前將它

ASP.net Mvc SportsSpore專案開發(二

1.新增導航控制元件為了使客戶能通過產品分類對其進行導航,需要從三面著手:1)增強Product Controller類中的List動作模型,以使它能夠過濾儲存庫中的Product物件。2)重新檢查並增強URL方案,並且修改路由配置。3)   建立一個產品分類列表,將其放入網

ASP.net Mvc SportsSpore專案開發(五

1.新增分類管理此次需要實現的是對物品資訊的讀取,新增更新和刪除的操作。這些動作統稱為“CRUD”。建立CRUD控制器,在Controllers檔案下新增控制器AdminControllerusing System; using System.Collections.Gene

asp.net mvc 模組化開發第一章(平臺介紹

基本框架是平臺+模組,其實說實在我也不知道這算框架還是算設計,或者說什麼都不算,希望大神們不要見笑,暫且我們叫他框架吧?這種框架源自於我上一家公司,當時我們公司有一個建站平臺和大家現在用CMS系統很像,不過功能沒有那麼強大,但是非常實用。這個平臺我用了將近三年,給我最大的感受

使用Visual Studio 2015 開發ASP.NET MVC 5 專案部署到Mono/Jexus

最新的Mono 4.4已經支援執行asp.net mvc5專案,有的同學聽了這句話就興高采烈的拿起Visual Studio 2015建立了一個mvc 5的專案,然後部署到Mono上,瀏覽下發現一堆錯誤出現,心中一萬隻草泥馬奔騰而來,這也叫支援嗎,這個問題是Visual Studio造成的,不相信的話可以使用

ASP.NET MVC搭建專案後臺UI框架—6、客戶管理(新增、修改、查詢、分頁

目錄 接著之前未寫完的繼續,本篇,我將講解在此UI框架中和ASP.NET MVC4進行結合開發。效果如下: 這裡,我將新增和修改用了兩個不同的檢視,當然也可以把新增和修改放到同一個檢視中,但是要寫一些業務邏輯程式碼來區分當前呼叫的是修改還是新增,根據新增和修改的不同,而對介面進行不同的操作。 新

ASP.NET MVC模組化開發——動態掛載外部專案

最近在開發一個MVC框架,開發過程中考慮到以後開發依託於框架的專案,為了框架的維護更新升級,程式碼肯定要和具體的業務工程分割開來,所以需要解決業務工程掛載在框架工程的問題,MVC與傳統的ASP.NET不同,WebForm專案只需要掛在虛擬目錄拷貝dll就可以訪問,但是MVC不可能去引用工程專案的dll重新編譯

.net異步性能測試(包括ASP.NET MVC WebAPI異步方法

睡眠時間 問題 none seconds await 數字 val http httpget 很久沒有寫博客了,今年做的產品公司這兩天剛剛開了發布會,稍微清閑下來,想想我們做的產品還有沒有性能優化空間,於是想到了.Net的異步可以優化性能,但到底能夠提升多大的比例呢?恰好有

asp.net mvc+jquery easyui開發實戰教程之網站後臺管理系統開發2-Model層建立

ack 前端 strong syn eee 名稱 lar led tegra 上篇(asp.net mvc+jquery easyui開發實戰教程之網站後臺管理系統開發1-準備工作)文章講解了開發過程中的準備工作,主要創建了項目數據庫及項目,本文主要講解項目M層的實現,M層

Asp.net MVC 中 CodeFirst 開發模式例項

  昨天寫的這篇部落格因為下班時間到了忘記儲存了,好鬱悶,得重新寫一遍。實習所在公司使用的是CodeFirst開發模式,最近開始參與到公司的專案裡面來了,發現這個模式特別好用,建庫建表改變欄位屬性新增刪除欄位等等操作都無需自己在資料庫動手操作,只需要編寫程式碼即可實現,著實是方便了許多。今天來記錄一下如何使用

ASP.Net MVC OA專案筆記<六>

1.1.1 開始寫業務,先寫業務的實現再寫業務的介面          業務類中也是有寫增刪改查公用的方法          引用Model,IDAL,DALFactory     &

如何提高碼農產量,基於ASP.NET MVC的敏捷開發框架開發隨筆一

公司業務量比較大,接了很多專案,為了縮短開發週期老闆讓我牽頭搭建了一個敏捷開發框架。 我們主要的業務是做OA、CRM、ERP一類的管理系統,一個通用的後臺搭出來,再配合一些快速開發的元件開發效率能提高很多。 另外老闆一再強調要支援APP開發,一次開發能部署到安卓和IOS上。

Asp.net mvc 知多少(一

本節主要講解MVC的基本概念 Q1. 什麼是MVC? Ans. MVC是Model-View-Controller的簡稱。它是在1970年引入的軟體設計模式。MVC 模式強迫關注分離 — 域模型和控制器邏輯與UI是鬆耦合關係。從而使應用程式的維護和測試更加簡單容易。 Q2. 解釋一下MVC設計模式? A

ASP.NET MVC搭建專案後臺UI框架—1、後臺主框架

目錄 準備做一個新的專案,從網頁設計師手中拿到了html靜態頁面(沒有一行js),但是都一個個零散的介面,我需要做的是: 1、  把這些零散的html介面連線起來 2、  自己編寫js或者jquery實現選單效果 3、  把html頁面整合在我們的MVC Razor檢視中 本想著使用第三方的UI

ASP.NET MVC搭建專案後臺UI框架—8、將View中選擇的資料行中的部分資料傳入到Controller中

目錄 現在,有一個需求,我需要將表格中選中行的資料中的一部分傳直接傳到控制器中,然後儲存到另外一張表中。一開始,我就想到在前臺使用ajax構造json資料,然後控制器直接通過list接收。 選中介面中的行,然後點選“批量新增到月結表”,彈出一個對話方塊,這個對話方塊的月份列表為當前選擇資料行中

ASP.NET MVC搭建專案後臺UI框架—2、選單特效

目錄 上一篇,已經把整個專案的框框給搭建好了,但是還沒有任何js效果實現。這一節,我就來說下關於選單的特效實現。我需要的效果如下: 需求總結: 點選頂部選單模組,左側顯示不同模組下面的選單列表 點選左側選單選項,展開下面的子選單,並摺疊其它選單模組,選單圖示摺疊顯示為+,展開顯示為

ASP.NET MVC搭建專案後臺UI框架—3、面板摺疊和展開

目錄 上一節已經新增好了選單特效,這一節,我們來新增面板的摺疊和展開功能,效果圖如下: 思路:我在Right檢視中添加了一個div,在這個div中存放一張圖片,通過對這張圖片的點選,來控制Left檢視的隱藏和顯示。說白了,這裡其實就是修改主框架Index檢視中frameset的 cols屬性。

ASP.NET MVC搭建專案後臺UI框架—7、統計報表

本節,我將通過一個Demo,演示Datatables 和ASP.NET MVC的完美結合,可以這麼說,如果這樣的介面都能做出來,後臺系統90%的介面功能都可以開發出來了。 用jquery Datatables 來開發確實是件比較蛋疼的事情(和Jquery EasyUI、MiniUI、ExtJs相比),用

ASP.NET MVC搭建專案後臺UI框架—11、自動載入下拉框查詢

需求:在查詢記錄的時候,輸入第一個字,就自動把以這個字開頭的相關記錄查找出來,輸入2個字就過濾以這兩個子開頭的記錄,依次類推。 突然要用到這個功能了,印象中曾經寫過這個功能的文章,一下子找不到了,只好重新貼出來備忘。最近部落格快2個月沒更新了,因為這兩個月一直在閉門寫書。   <link

ASP.NET MVC搭建專案後臺UI框架—9、伺服器端排序

關於jquery datables的在伺服器端的排序,在網上貌似沒有看到.NET的例子,說實話,之前我也迷惑過,習慣了直接從網上找現成的東西,經過一翻搜尋,沒找到,於是乎,自己除錯唄,調了前臺,調後臺,還真被我看出了規律。事實上datables是支援多列排序的,但是本例,我只寫了單列排序。 在控制器