讀這篇文章不意味着你必定要去而且能搞定MVC面試。這篇文章的目的是在面試以前讓你快速複習MVC知識。這篇文章也不是MVC培訓課程。javascript
若是你想學習MVC,從這兒開始 Learn MVC ( Model view controller) step by step 7 days ,或者是 step by step MVC (Model View Controller) video series from YouTube.php
MVC是一個架構模式,它分離了表現與交互。它被分爲三個核心部件:模型、視圖、控制器。下面是每個部件的分工:css
下面是MVC(模型、視圖、控制器)架構的控制流程:html
相比Windows應用,MVC架構更適用於Web應用。對於Windows應用,MVP(Model View Presenter )架構更好一點。若是你使用WPF和Silverlight,MVVM更適合。java
MVC有兩個大的好處:jquery
MVC是三層傳統架構的演變。三層架構和MVC有一些通用的組成部分。 顯示以下:nginx
功能性 | 三層 / 分層架構 | Model view controller architecture |
顯示與交互 | 用戶界面 | 視圖 |
UI邏輯 | 用戶界面 | 控制器 |
商業邏輯 / 驗證 | 中間層 | 模型 |
請求首先發送給誰? | 用戶界面 | 控制器 |
訪問數據 | 數據連接層 | 數據連接層 |
在寫這篇文章時MVC已經發行了4個版本:MVC 1 , MVC 2, MVC 3, 和 MVC 4. 因此 MVC 4是最新版本。web
下面的表格列出了詳細的不一樣點。可是在面試中限於時間問題,很難去說出全部的東西。因此,我標出了全部重要區別。面試
MVC 2 | MVC 3 | MVC 4 |
|
|
|
HTML helpers幫助你渲染視圖中的HTML控件。若是在面試中你想展現HTML輸入框,下面是HTML helper代碼。瀏覽器
<%= Html.TextBox("LastName") %>
checkbox的代碼以下。用這種方式咱們能夠建立現存的全部HTML控件。
<%= Html.CheckBox("Married") %>
它們兩個輸出相同的HTML, 「HTML.TextBoxFor」是強類型的,但 「HTML.TextBox」不是。下面是一個實例,它僅僅建立了一個名字爲 「CustomerCode」的輸入框。
Html.TextBox("CustomerCode")
下面的代碼是用 「Html.TextBoxFor」 建立的HTML輸入框,從對象"m"中調用了屬性」CustomerCode 「。
Html.TextBoxFor(m => m.CustomerCode)
相同的方式,咱們能夠用「Html.CheckBox」 和 「Html.CheckBoxFor」建立checkbox。
路由選擇功能幫你定義一個URL規則,映射URL到控制器。
舉一個例子,咱們想讓用戶輸入「 http://localhost/View/ViewCustomer/ 」時,它轉向到「Customer」控制器而且調用 DisplayCustomer
。這個經過Maproute方法來定義。代碼以下:
routes.MapRoute(
"View", // Route name "View/ViewCustomer/{id}", // URL with parameters new { controller = "Customer", action = "DisplayCustomer", id = UrlParameter.Optional }); // Parameter defaults
在 「 global.asax 」 文件。
是的,能夠。只須要添加多條不一樣Key名字的記錄,而且指定一樣的控制器和動做。
使用 ActionLink
方法,以下圖所示。下面的代碼生成一個簡單的URL,連接到"Home"控制器的GotoHome動做。
<%= Html.ActionLink("Home","Gotohome") %>
咱們能夠給MVC的動做一個HttpGet或HttpPost屬性去限制HTTP的類型。你能夠看下面的代碼段,這個 DisplayCustomer
動做只能用HttpGet方式訪問。若是咱們嘗試用Http post的方式,會看到錯誤信息。
[HttpGet]
public ViewResult DisplayCustomer(int id) { Customer objCustomer = Customers[id]; return View("DisplayCustomer",objCustomer); }
能夠經過三種方式保持: tempdata, viewdata, 和viewbag。
下表是彙總:
Maintains data between | ViewData/ViewBag | TempData | Hidden fields | Session |
Controller to Controller | No | Yes | No | Yes |
Controller to View | Yes | No | No | Yes |
View to Controller | No | No | Yes | Yes |
局部視圖是一個可重複調用的視圖(和用戶控件同樣),它能夠嵌入到視圖裏面。例如:你的站點頁面有統一的菜單、頭部、尾部,以下圖所示:
若是你想在全部頁面重用菜單、頭部和尾部。能夠建立局部視圖,而後在主視圖中調用它們。
點擊"Create partial view "複選框去添加局部視圖。
局部視圖建立好後,在主視圖中使用 Html.RenderPartial
調用。以下代碼:
<body> <div> <% Html.RenderPartial("MyView"); %> </div> </body>
早期的MVC版本中使用數據註釋來作驗證。除了註釋還能夠利用數據模型的屬性標籤。例如,下面的實例代碼中Customer類有一個屬性customercode。
這個CustomerCode屬性標註了一個Required數據。若是不提供CustomerCode數據,它將不能經過驗證。
public class Customer { [Required(ErrorMessage="Customer code is required")] public string CustomerCode { set; get; } }
爲了顯示驗證錯誤提示咱們須要使用ValidateMessageFor方法,它屬於Html helper類。
<% using (Html.BeginForm("PostCustomer", "Home", FormMethod.Post)) { %> <%=Html.TextBoxFor(m => m.CustomerCode)%> <%=Html.ValidationMessageFor(m => m.CustomerCode)%> <input type="submit" value="Submit customer data" /> <%}%>
在controller中,使用ModelState.IsValid屬性檢查數據是否正確。
public ActionResult PostCustomer(Customer obj)
{
if (ModelState.IsValid) { obj.Save(); return View("Thanks"); } else { return View("Customer"); } }
下面是一個顯示錯誤信息的實例。
能夠。使用Html helper類中的ValidationSummary方法。
<%= Html.ValidationSummary() %>
MVC中還有哪些註釋屬性用來驗證?
若是你要去檢查字符的長度,你可使用 StringLength
.
[StringLength(160)]
public string FirstName { get; set; }
若是你想使用註冊表達式,你可使用 RegularExpression
。
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]public string Email { get; set; }
若是你想檢查數字是否在一個範圍內,你可使用 Range
。
[Range(10,25)]public int Age { get; set; }
有時你想比較兩個字段的值,咱們可使用 Compare
。
public string Password { get; set; }[Compare("Password")]public string ConfirmPass { get; set; }
若是你想拿到錯誤詳情,你可使用 Errors
集合。
var ErrMessage = ModelState["Email"].Errors[0].ErrorMessage;
若是你已經建立好模型對象,你能夠在Contronller中調用 TryUpdateModel
去檢查它是否正確。
TryUpdateModel(NewCustomer);
若是你想在Controller中添加錯誤信息,你可使用 AddModelError
函數。
ModelState.AddModelError("FirstName", "This is my server-side error.");
有兩個步驟:第一引用必須的jQuery文件。
<script src="<%= Url.Content("~/Scripts/jquery-1.5.1.js") %>" type="text/javascript"></script> <script src="<%= Url.Content("~/Scripts/jquery.validate.js") %>" type="text/javascript"></script> <script src="<%= Url.Content("~/Scripts/jquery.validate.unobtrusive.js") %>" type="text/javascript"></script>
第二步去調用 EnableClientValidation
方法。
<% Html.EnableClientValidation(); %>
它是一個輕量級的視圖引擎。MVC最初只有一個ASPX的視圖類型,直到MVC3才引進了Razor 。
相比ASPX,Razor是一個乾淨的、輕量級的和語法更簡單。例如,ASPX去顯示時間:
<%=DateTime.Now%>
在Razor中,只須要一行:
@DateTime.Now
Razor更好,由於它是輕量級的,而且語法簡單。
在MVC中你可使用Windows或Forms認證。
你須要修改web.config文件,並設置驗證模式爲Windows。
<authentication mode="Windows"/> <authorization> <deny users="?"/> </authorization>
而後在controlle或action中,你可使用 Authorize
屬性,指定哪一個用戶能夠訪問這個controller或action。下面的代碼設置到只有指定的用戶能夠訪問它。
[Authorize(Users= @"WIN-3LI600MWLQN\Administrator")]
public class StartController : Controller { // // GET: /Start/ [Authorize(Users = @"WIN-3LI600MWLQN\Administrator")] public ActionResult Index() { return View("MyView"); } }
表單認證和ASP.NET的表單驗證同樣。第一步是設置認證模式爲Forms。loginUrl是指向到controller,而不是一個頁面。
<authentication mode="Forms"> <forms loginUrl="~/Home/Login" timeout="2880"/> </authentication>
咱們也須要建立一個controller,去驗證用戶。若是驗證經過,須要設置cookies值。
public ActionResult Login()
{
if ((Request.Form["txtUserName"] == "Shiv") && (Request.Form["txtPassword"] == "Shiv@123")) { FormsAuthentication.SetAuthCookie("Shiv",true); return View("About"); } else { return View("Index"); } }
其它須要驗證的action都須要加一個 Authorize
屬性,若是用戶沒權限將轉向到登錄頁面。
[Authorize]
PublicActionResult Default() { return View(); } [Authorize] publicActionResult About() { return View(); }
MVC中有兩種方式能夠執行AJAX:
下面是一個簡單的實例,它使用「AJAX」幫助執行AJAX。在下面的代碼中,你可使用Ajax.BeginForm建立了一個表單。這個表單調用了一個getCustomer方法。
<script language="javascript"> function OnSuccess(data1) { // Do something here } </script> <div> <% var AjaxOpt = new AjaxOptions{OnSuccess="OnSuccess"}; %> <% using (Ajax.BeginForm("getCustomer","MyAjax",AjaxOpt)) { %> <input id="txtCustomerCode" type="text" /><br /> <input id="txtCustomerName" type="text" /><br /> <input id="Submit2" type="submit" value="submit"/></div> <%} %>
若是你想作在hyperlink點擊上作Ajax調用,你可使用 Ajax.ActionLink
函數,以下圖所示。
若是你想建立一個AJAX異步hyperlink,它調用controller中的GetDate方法,代碼以下。一旦controller做出迴應,這個數據會顯示在id爲DateDiv的DIV中。
<span id="DateDiv" /> <%: Ajax.ActionLink("Get Date","GetDate", new AjaxOptions {UpdateTargetId = "DateDiv" }) %>
下面是Controller代碼。你能夠看到GetDate有延遲10秒。
public class Default1Controller : Controller { public string GetDate() { Thread.Sleep(10000); return DateTime.Now.ToString(); } }
在MVC中作Ajax調用的第二種方式是使用jQuery。下面的代碼你能夠看到咱們作了一個AJAX POST到 /MyAjax/getCustomer。 它 使用$.post。全部的邏輯代碼放在GetData函數中,你能夠經過一個按鈕或者是連接點擊事件去調用它。
function GetData() { var url = "/MyAjax/getCustomer"; $.post(url, function (data) { $("#txtCustomerCode").val(data.CustomerCode); $("#txtCustomerName").val(data.CustomerName); } ) }
ActionResult
是一個抽象類,ViewResult衍生於 ActionResult
類。 ActionResult
有幾種衍生類,例如: ViewResult
, JsonResult
,
FileStreamResult
, 等等。ActionResult
能夠用來開發多態和動態動象。因此若是你動態運行不一樣類型的視圖, ActionResult
是最好的選擇。例以下面的代碼,你能夠看見咱們有一個 DynamicView 。基於標記(IsHtmlView),它會返回 ViewResult
或 JsonResult
。 public ActionResult DynamicView()
{
if (IsHtmlView) return View(); // returns simple ViewResult else return Json(); // returns JsonResult view }
注意: 很難去記住全部的12種類型。可是一些重要的你能夠記住,例如: ActionResult
, ViewResult
,和 JsonResult
。詳情以下:
MVC中的12種結果類型,最主要的是ActionResult類,它是一個基礎類,它有11個子類型,以下:
ViewResult
- 給響應流渲染指定的視圖PartialViewResult
- 給響應流渲染指定的局部視圖EmptyResult
- 返回空的響應結果。RedirectResult
- 執行一個HTTP轉向到指定的URL。RedirectToRouteResult
- 執行一個HTTP轉向到一個URL,這個URL由基於路由數據的路由引擎來決定JsonResult
- 序列化一個ViewData對像到JSON格式。JavaScriptResult
- 返回一段Javascript代碼,它能夠在客戶端執行。ContentResult
- 寫內容到響應流,不須要視圖支持。FileContentResult
- 返回一個文件到客戶端。FileStreamResult
- 返回一個文件到客戶端,它提供的是流。FilePathResult
- 返回一個文件到客戶端。ActionFilters幫助你在MVC action執行中或執行後,執行一些邏輯。
Action filters一般用在下面的場景中:
你有兩種方式建立action filters:
ActionFilter
屬性.建立內聯action filter,咱們須要執行 IActionFilter
接口。 IActionFilter
接口有兩個方法: OnActionExecuted
和 OnActionExecuting
。在這兩個方法中咱們能夠執行預處理邏輯或取消邏輯。
public class Default1Controller : Controller , IActionFilter { public ActionResult Index(Customer obj) { return View(obj); } void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) { Trace.WriteLine("Action Executed"); } void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { Trace.WriteLine("Action is executing"); } }
內聯Action filter的問題是不能跨Controler。咱們能夠轉換內聯action filter到action filter屬性。建立action filter屬性,咱們須要繼承 ActionFilterAttribute 和執行 IActionFilter
接口,代碼以下:
public class MyActionAttribute : ActionFilterAttribute , IActionFilter { void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) { Trace.WriteLine("Action Executed"); } void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { Trace.WriteLine("Action executing"); } }
以後咱們能夠在controller上使用這個屬性。你能夠看下面的代碼:
[MyActionAttribute]
public class Default1Controller : Controller { public ActionResult Index(Customer obj) { return View(obj); } }
能夠,在MVC中咱們能夠建立本身的自定義視圖引擎。建立本身的自定義視圖引擎須要跟隨下面三步:
咱們將建立一個自定義視圖引擎,在視圖裏用戶能夠輸入一個命令,好比「<DateTime>」,它會顯示當前的日期和時間。
步驟1 :咱們須要建立一個類去執行IView接口。咱們應該 在這個類的render函數中寫一些邏輯,指明如何渲染視圖。示例代碼以下:
public class MyCustomView : IView { private string _FolderPath; // Define where our views are stored public string FolderPath { get { return _FolderPath; } set { _FolderPath = value; } } public void Render(ViewContext viewContext, System.IO.TextWriter writer) { // Parsing logic <dateTime> // read the view file string strFileData = File.ReadAllText(_FolderPath); // we need to and replace <datetime> datetime.now value string strFinal = strFileData.Replace("<DateTime>", DateTime.Now.ToString()); // this replaced data has to sent for display writer.Write(strFinal); } }
步聚2: 咱們須要建立一個類,它繼承 VirtualPathProviderViewEngine
,而且咱們須要提供一個文件夾路徑和視圖文件擴展名。例如,Razor是「cshtml」,aspx是「.aspx」。示例代碼以下:
public class MyViewEngineProvider : VirtualPathProviderViewEngine { // We will create the object of Mycustome view public MyViewEngineProvider() // constructor { // Define the location of the View file this.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.myview", "~/Views/Shared/{0}.myview" }; //location and extension of our views } protected override IView CreateView( ControllerContext controllerContext, string viewPath, string masterPath) { var physicalpath = controllerContext.HttpContext.Server.MapPath(viewPath); MyCustomView obj = new MyCustomView(); // Custom view engine class obj.FolderPath = physicalpath; // set the path where the views will be stored return obj; // returned this view paresing // logic so that it can be registered in the view engine collection } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { var physicalpath = controllerContext.HttpContext.Server.MapPath(partialPath); MyCustomView obj = new MyCustomView(); // Custom view engine class obj.FolderPath = physicalpath; // set the path where the views will be stored return obj; // returned this view paresing logic // so that it can be registered in the view engine collection } }
步驟 3: 咱們須要註冊自定義視圖到視圖集合。註冊自定義視圖引擎最適合的地方是global.aspx文件中的 ViewEngines
集合。 代碼以下:
protected void Application_Start() { // Step3 :- register this object in the view engine collection ViewEngines.Engines.Add(new MyViewEngineProvider()); ….. }
下面是一個實例,在自定義視圖的頂部中寫了一個定義好的命令。
當你調用視圖,你應該能看見下面的輸出:
在MVC中,咱們有 JsonResult
類能夠返回JSON格式數據。下面是一個簡單的例子,它使用JsonResult返回Customer對象的JSON格式。
public JsonResult getCustomer() { Customer obj = new Customer(); obj.CustomerCode = "1001"; obj.CustomerName = "Shiv"; return Json(obj,JsonRequestBehavior.AllowGet); }
下面是上面代碼的JSON輸出:
HTTP是最經常使用的協議。過去的不少年,瀏覽器是咱們使用HTTP方式公開數據的首選客戶端。可是突飛猛進,客戶端發展到多種形式。咱們須要使用HTTP方式傳遞數據給不一樣的客戶端,例如:移動手機、Javascript,Windows應用等等。
WebAPI是一個經過HTTP方式公開數據的技術,它跟隨REST規則。
SOAP | WEB API | |
大小 | 重量級,由於它使用複雜的WSDL結構。 | 輕量級,只有須要的信息被傳遞。 |
協議 | 協議無關 | 只支持HTTP協議 |
格式 | 解析SOAP信息,客戶端須要理解WSDL格式。寫自定義代碼去解析WSDL是很是重要的任務。若是客戶端足夠聰明去建立一個代理對象,好比在.net中添加引用,那麼SOAP是最簡單的方式。 | WebAPI的輸出是簡單的字符串、JSON、簡單XML格式等。因此,寫解析邏輯很是簡單。 |
規則 | SOAP跟隨WS-* 規定 | WebAPI跟隨REST規定。(Please refer to REST in WCF chapter.) |
在控制器中識別POST或GET,咱們可使用 Request.HttpMethod
,代碼以下所示:
public ActionResult SomeAction()
{
if (Request.HttpMethod == "POST") { return View("SomePage"); } else { return View("SomeOtherPage"); } }
打包與壓縮幫助咱們減小一個頁面的請求時間,從而提升頁面執行性能。
咱們的項目老是須要CSS和腳本文件。打包幫助你合併多個Javascript和css文件到單個文件,從而最小化多個請求到一個請求。
例如,包含下面的web請求到一個頁。這個頁面要求兩個Javascript文件, Javascript1.js 和 Javascript2.js 。 當請求這個頁面時,它要作三次請求:
若是頁面中有大量的javascript文件,這樣會下降性能。若是咱們能夠合併全部的JS文件到一個文件,只請求一個,這將加增長性能。以下圖所示:
打開 App_Start 文件夾中的 BundleConfig.cs
在 BundleConfig.cs 中,添加你想打包的JS文件路徑到打包集合。以下所示:
bundles.Add(new ScriptBundle("~/Scripts/MyScripts").Include( "~/Scripts/*.js"));
下面是 BundleConfig.cs 文件的代碼:
public class BundleConfig { public static void RegisterBundles(BundleCollection bundles) { bundles.Add(new ScriptBundle("~/Scripts/MyScripts").Include( "~/Scripts/*.js")); BundleTable.EnableOptimizations = true; } }
一旦你合併了腳本到一個文件,你可使用下面的代碼去調用它:
<%= Scripts.Render("~/Scripts/MyScripts") %>
你將看到腳本請求被合併到一個:
若是你在debug模式下,你須要在bundleconfig.cs中設置 EnableOptimizations
爲true,不然你不會看到打包效果。
BundleTable.EnableOptimizations = true;
壓縮功能經過移除空格、註釋等減小了腳本與CSS文件的大小。例以下面的代碼:
// This is test var x = 0; x = x + 1; x = x * 2;
執行壓縮後的Javascript代碼以下所示。
var x=0;x=x+1;x=x*2;