視圖(View)html
表明用戶交互界面,對於Web應用來講,能夠歸納爲HTML界面,但有可能爲XHTML、XML和Applet。 git
模型(Model)github
表示用戶對其數據的操做的一個封轉。能夠分爲視圖模型(view model)和領域模型(domain models),視圖模型就是在視圖與控制器之間傳輸數據的一個封轉,而領域模型就是業務邏輯,後臺數據模型等的一個集合。是咱們學的3層中的BLL,DAL,Models的集合 數據庫
控制器(Controller)瀏覽器
控制器能夠理解爲從用戶接收請求,將模型與視圖匹配在一塊兒,共同完成用戶的請求。框架
當在瀏覽器中輸入一個URL,進入了Route系統,路由系統獲得URL各個片斷的值,並交給MVC處理,MVC依據URL的信息知道請求的Action,接着就對模型進行一系列的處理,而後呈現視圖。dom
MVC對控制器與View有必定的限制,但對模型沒有任何的限制。ide
控制器必須實現IController接口或者繼承Controller類,控制器類中的公有方法稱之爲Action Method。工具
在MVC項目中有2種習慣佈局
a、建議你如何組織項目中的一些文件,好比js文件放在Scripts文件夾下,像這種習慣,你徹底能夠不遵循,這些文件夾和文件刪除並不影響MVC框架自己。
b、另一種,有個專門的術語:」Convention over configuration」,意思就是說若是你遵循了這個習慣就不須要進行額外的配置或編碼(特別是控制器與視圖)。這種習慣就儘可能遵循,若是違反,在MVC中就須要作許多的事情。
主要有3個方面:
a、控制器命名習慣:控制器類必須以Controller結尾,但引用這個控制器的時候能夠省略掉Controller,若是想改變這種行爲,須要本身實現IControllerFactory接口,默認是經過DefaultControllerFactory來執行這個控制器的查找的。
b、視圖命名習慣:視圖或者分部視圖應該放在/Views/Controllername文件夾下面,好比一個控制器爲Demo 那麼這個控制器的全部視圖應該放在/Views/Demo/下面,默認狀況下,每個Action Method對應一個視圖,盡
量讓視圖名字與Action名字同樣,這樣在Action中就能夠直接return View();而放在Shared文件夾下面的視圖全部的控制器均可以使用
c、佈局命名習慣:佈局文件都如下劃線開頭,並放置在shared文件夾下面,在MVC 3中默認每一個視圖都會用到_layout.cshtml佈局,能夠在_viewstart.cshtml看到這個設置
優勢:
A、具備多個視圖對應一個模型的能力。
B、因爲一個應用被分離爲三層,所以有時改變其中的一層就能知足應用的改變。一個應用的業務流程或者業務規則的改變只需改動MVC的模型層。
C、它還有利於軟件工程化管理。因爲不一樣的層各司其職,每一層不一樣的應用具備某些相同的特徵,有利於經過工程化、工具化產生管理程序代碼。
缺點:
A、增長了系統結構和實現的複雜性。
B、視圖與控制器間的過於緊密的鏈接。
C、視圖對模型數據的低效率訪問。
建立第一個MVC應用程序以前,首先說明一下個人電腦使用配置環境:VS2013與SQLSever2012。
1、首先打開VS2013,新建一個MVC4項目。
2、點擊肯定後會彈出以下圖界面。
3、點擊肯定後會自動生成以下默認項目結構。
四、在Controller文件夾上右鍵添加一個控制器。
五、點擊添加按鈕後,生成HomeController類,默認生成Index()方法以下:
六、如今Controller控制器已經建立好了,下面來建立一個View視圖了,添加添加視圖兩種方式:方式一:在控制器裏的Index()方法裏右鍵添加視圖,方式二:在View文件夾上右鍵添加一個與HomeController控制器名稱相同的文件夾如:Home文件夾,在該文件夾上右鍵添加一個與Index()方法同名的視圖。這裏選擇選擇方式一建立方法以下所示:
七、最終添加視圖後的界面,開始運行瀏覽查看結果。
到這裏咱們的第一個MVC程序Hello World就完成了,是否是感受很簡單。那麼接下來就來學習寫一個關於Asp.Net MVC的增刪改查的簡單測試案例吧。已經學習過Asp.Net的同窗能夠先思考一下如何用MVC實現一個增刪改查的的功能。沒有學習過的同窗能夠思考下邏輯三層與MVC中Model的聯繫,下面這個簡單測試案例將讓你對MVC概念的理解的更明白些。
測試案例增刪改查效果圖以下:
一、首先準備數據庫數據。
use master go create database Demo go use Demo go create table Product ( ID int primary key identity(1,1), Name nvarchar(20), Price decimal ) go insert into Product values('電腦墊',22),('鼠標',55),('鍵盤',22),('網線',32),('U盤',100),('咖啡',55),('書籍',99),('牛奶',5) go
二、打開VS2013建立一個名爲MvcFristDemo的MVC4項目,建立步驟與上面一致,這裏步驟再也不詳細介紹,最終項目建立完成截圖以下。
這裏須要說明一下添加視圖的步驟與上面Hello World示例有所區別:由於要用到Model模型,因此在添加視圖的時候須要選中以下圖中的建立強類型視圖 模型選擇Product模型。
三、步驟一:ProductController控制器代碼以下。
1 using MvcFirstDemo.Models; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Mvc; 7 8 namespace MvcFirstDemo.Controllers 9 { 10 public class ProductController : Controller 11 { 12 public ActionResult List() 13 { 14 List<Product> result = new ProductBll().Select(); 15 return View(result); 16 } 17 18 19 public ActionResult Add() 20 { 21 return View(); 22 } 23 [HttpPost] 24 public ActionResult Add(Product p) 25 { 26 bool result = new ProductBll().Insert(p); 27 return RedirectToAction("List"); 28 } 29 30 public ViewResult Update(int id) 31 { 32 Product p = new ProductBll().GetProductById(id); 33 return View(p); 34 } 35 [HttpPost] 36 public ActionResult Update(Product p) 37 { 38 bool result = new ProductBll().Update(p); 39 return RedirectToAction("List"); 40 } 41 42 public ActionResult Delete(int id) 43 { 44 bool result = new ProductBll().Delete(id); 45 return RedirectToAction("List"); 46 } 47 } 48 }
四、步驟二:Model文件夾中的三個類代碼以下。
Product.cs代碼以下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace MvcFirstDemo.Models 7 { 8 public class Product 9 { 10 public int ID { get; set; } 11 public string Name { get; set; } 12 public decimal Price { get; set; } 13 } 14 }
ProductBll.cs代碼以下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace MvcFirstDemo.Models 7 { 8 public class ProductBll 9 { 10 ProductDal dal = new ProductDal(); 11 public List<Product> Select() 12 { 13 return dal.Select(); 14 } 15 public Product GetProductById(int id) 16 { 17 return dal.GetProductById(id); 18 } 19 public bool Update(Product p) 20 { 21 return dal.Update(p); 22 } 23 24 public bool Insert(Product p) 25 { 26 return dal.Insert(p); 27 } 28 29 public bool Delete(int id) 30 { 31 return dal.Delete(id); 32 } 35 } 36 }
ProductDal.cs代碼以下:
1 using System; 2 using System.Collections.Generic; 3 using System.Data.SqlClient; 4 using System.Linq; 5 using System.Web; 6 7 namespace MvcFirstDemo.Models 8 { 9 public class ProductDal 10 { 11 string connStr = @"server=PC-201511211346\MSSQLSERVER2;database=Demo;uid=sa;pwd=123456;"; 12 public List<Product> Select() 13 { 14 using (SqlConnection conn = new SqlConnection(connStr)) 15 { 16 conn.Open(); 17 string SQL = "select * from Product"; 18 SqlCommand cmd = new SqlCommand(SQL, conn); 19 using (SqlDataReader sdr = cmd.ExecuteReader()) 20 { 21 List<Product> list = new List<Product>(); 22 Product obj = null; 23 while (sdr.Read()) 24 { 25 obj = new Product 26 { 27 ID = Convert.ToInt32(sdr["ID"]), 28 Name = sdr["Name"].ToString(), 29 Price = Convert.ToDecimal(sdr["Price"]) 30 }; 31 list.Add(obj); 32 } 33 return list; 34 } 35 } 36 } 37 38 public bool Insert(Product p) 39 { 40 using (SqlConnection conn = new SqlConnection(connStr)) 41 { 42 conn.Open(); 43 string SQL = "insert into Product values(@Name,@Price)"; 44 SqlCommand cmd = new SqlCommand(SQL, conn); 45 cmd.Parameters.AddWithValue("Name", p.Name); 46 cmd.Parameters.AddWithValue("Price", p.Price); 47 return cmd.ExecuteNonQuery() > 0 ? true : false; 48 } 49 } 50 51 public bool Update(Product p) 52 { 53 using (SqlConnection conn = new SqlConnection(connStr)) 54 { 55 conn.Open(); 56 string SQL = "update Product set Name=@Name,Price=@Price where ID=@ID"; 57 SqlCommand cmd = new SqlCommand(SQL, conn); 58 cmd.Parameters.AddWithValue("@ID", p.ID); 59 cmd.Parameters.AddWithValue("@Name", p.Name); 60 cmd.Parameters.AddWithValue("@Price", p.Price); 61 62 return cmd.ExecuteNonQuery() > 0 ? true : false; 63 } 64 } 65 66 public bool Delete(int id) 67 { 68 using (SqlConnection conn = new SqlConnection(connStr)) 69 { 70 conn.Open(); 71 string SQL = "delete from Product where ID=@ID"; 72 SqlCommand cmd = new SqlCommand(SQL, conn); 73 cmd.Parameters.AddWithValue("@ID", id); 74 return cmd.ExecuteNonQuery() > 0 ? true : false; 75 } 76 } 77 78 internal Product GetProductById(int id) 79 { 80 using (SqlConnection conn = new SqlConnection(connStr)) 81 { 82 conn.Open(); 83 string SQL = "select * from Product where ID=@ID"; 84 SqlCommand cmd = new SqlCommand(SQL, conn); 85 cmd.Parameters.AddWithValue("@ID", id); 86 using (SqlDataReader sdr = cmd.ExecuteReader()) 87 { 88 Product obj = null; 89 while (sdr.Read()) 90 { 91 obj = new Product 92 { 93 ID = Convert.ToInt32(sdr["ID"]), 94 Name = sdr["Name"].ToString(), 95 Price = Convert.ToDecimal(sdr["Price"]) 96 }; 97 } 98 return obj; 99 } 100 } 101 } 102 } 103 }
五、步驟三:View文件夾中三個視圖代碼以下。
這裏須要說明一下的是對List.aspx頁面中圖一中默認生成代碼改爲圖二中代碼,修改爲紅色部分代碼:<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<List<MvcFirstDemo.Models.Product>>" %>
爲何要這樣修改呢?由於咱們在ProductDal.cs類中的Select()方法返回的是list<Product>集合 ,而在List.aspx頁面中foreach須要遍歷一個List<Product>集合綁定顯示列表。若是你不作修改,運行程序後會出現以下圖所示錯誤。
List.aspx頁面代碼以下:
1 <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<List<MvcFirstDemo.Models.Product>>" %> 2 3 <!DOCTYPE html> 4 5 <html> 6 <head runat="server"> 7 <meta name="viewport" content="width=device-width" /> 8 <title>List</title> 9 </head> 10 <body> 11 <div> 12 <table cellspacing="1" border="1"> 13 <tr> 14 <td>產品ID</td> 15 <td>產品名稱</td> 16 <td>產品價格</td> 17 <td>操做 <a href="Product/Add">增長</a></td> 18 </tr> 19 <% 20 foreach (var item in Model) 21 { 22 %> 23 <tr> 24 <td><%=item.ID %></td> 25 <td><%=item.Name %></td> 26 <td><%=item.Price %></td> 27 <td> 28 <a href="/Product/Update?id=<%=item.ID %>">修改</a> 29 <a href="/Product/Delete?id=<%=item.ID %>">刪除</a> 30 </td> 31 </tr> 32 <% 33 } 34 %> 35 </table> 36 </div> 37 </body> 38 </html>
Add.aspx頁面代碼以下:
1 <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcFirstDemo.Models.Product>" %> 2 3 <!DOCTYPE html> 4 5 <html> 6 <head runat="server"> 7 <meta name="viewport" content="width=device-width" /> 8 <title>Add</title> 9 </head> 10 <body> 11 <div> 12 <form action="/Product/Add" method="post"> 13 <input type="text" name="Name" value=" " /> 14 <input type="text" name="Price" value=" " /> 15 <input type="submit" name="submit" value="增長" /> 16 </form> 17 </div> 18 </body> 19 </html>
Update.aspx頁面代碼以下:
1 <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcFirstDemo.Models.Product>" %> 2 3 <!DOCTYPE html> 4 5 <html> 6 <head runat="server"> 7 <meta name="viewport" content="width=device-width" /> 8 <title>Update</title> 9 </head> 10 <body> 11 <div> 12 <form action="/Product/Update" method="post"> 13 <input type="hidden" name="ID" value="<%=Model.ID%>" /> 14 <input type="text" name="Name" value="<%=Model.Name %>" /> 15 <input type="text" name="Price" value="<%=Model.Price %>" /> 16 <input type="submit" name="submit" value="修改" /> 17 </form> 18 </div> 19 </body> 20 </html>
解決辦法:此錯誤解決方式有三個,方式一:在圖二中Update(int id)方法修改爲能夠爲null的方法Update(int? id),方式二:給圖二中Update(int id)方法參數添加一個默認值如:Update(int id=0)便可。方式三:把圖二中的參數名dd改爲與圖一中傳遞的參數名id同樣的名字便可解決爲null問題得到數據。
解決辦法:在以下圖中方法重載代碼處,其中一個方法添加一個特性如[HttpPost]、[HttpPut]、[HttpPatch],便可解決此問題,至於添加哪一個特性須要依據你發起請求的方法而決定。
解決辦法:此問題的解決辦法在上面步驟三中已作解釋說明,這裏再也不重複解釋。
解決辦法:把下圖中的傳遞表單數據的參數名字改爲與Product模型類裏的字段名同樣便可得到表單傳遞過來的數據。
解決辦法:查看頁面代碼發現瀏覽器請求的頁面路徑並無錯誤,可是運行又確實報錯,找不到請求URL指定路徑的頁面,這該怎麼辦呢?咱們冷靜分析一下,這裏其實牽涉到了一個知識點,就是你對MVC原理的理解,在前面1.二、Asp.Net MVC的原理節中已經講到MVC的原理,因此這裏咱們只須要作以下圖所示修改便可解決此問題。
Github下載地址:https://github.com/SeeYouBug2/MvcFirstDemo.git
總結:在本文章中,主要是對理解ASP.NET MVC的相關概念作了個簡單介紹,以及經過一個MVC增刪改查簡單測試案例幫助初學者加深對MVC模式的理解,最後還總結了初學者幾個常見的錯誤,讓初學者少走點彎路。