讀這篇文章不意味著你一定要去并且能搞定MVC面試。這篇文章的目的是在面試之前讓你快速復(fù)習(xí)MVC知識(shí)。這篇文章也不是MVC培訓(xùn)課程。 如果你想學(xué)習(xí)MVC,從這兒開始 Learn MVC ( Model view controller) step by step 7 days ,或者是 step by step MVC (Model View Controller) video series from YouTube. 什么是MVC (模型 視圖 控制器)?MVC是一個(gè)架構(gòu)模式,它分離了表現(xiàn)與交互。它被分為三個(gè)核心部件:模型、視圖、控制器。下面是每一個(gè)部件的分工:
圖: MVC (模型、視圖、控制器)
你能解釋下MVC的完整流程嗎?下面是MVC(模型、視圖、控制器)架構(gòu)的控制流程:
MVC同時(shí)適用于Windows應(yīng)用和Web應(yīng)用嗎?相比Windows應(yīng)用,MVC架構(gòu)更適用于Web應(yīng)用。對(duì)于Windows應(yīng)用,MVP(Model View Presenter )架構(gòu)更好一點(diǎn)。如果你使用WPF和Silverlight,MVVM更適合。 使用MVC有哪些好處?MVC有兩個(gè)大的好處:
MVC不同于三層架構(gòu)?MVC是三層傳統(tǒng)架構(gòu)的演變。三層架構(gòu)和MVC有一些通用的組成部分。 顯示如下:
圖示: 三層架構(gòu)
MVC的最新版本是哪個(gè)?在寫這篇文章時(shí)MVC已經(jīng)發(fā)行了4個(gè)版本:MVC 1 , MVC 2, MVC 3, 和 MVC 4. 所以 MVC 4是最新版本。 每個(gè)版本的MVC有什么不同?下面的表格列出了詳細(xì)的不同點(diǎn)。但是在面試中限于時(shí)間問題,很難去說出所有的東西。所以,我標(biāo)出了所有重要區(qū)別。
MVC中的HTML helpers是什么?HTML helpers幫助你渲染視圖中的HTML控件。如果在面試中你想展示HTML輸入框,下面是HTML helper代碼。 <%= Html.TextBox("LastName") %> checkbox的代碼如下。用這種方式我們可以創(chuàng)建現(xiàn)存的所有HTML控件。 <%= Html.CheckBox("Married") %> “HTML.TextBox” 和 “HTML.TextBoxFor”有什么不同?它們兩個(gè)輸出相同的HTML, “HTML.TextBoxFor”是強(qiáng)類型的,但 “HTML.TextBox”不是。下面是一個(gè)實(shí)例,它僅僅創(chuàng)建了一個(gè)名字為 “CustomerCode”的輸入框。 Html.TextBox("CustomerCode") 下面的代碼是用 “Html.TextBoxFor” 創(chuàng)建的HTML輸入框,從對(duì)象"m"中調(diào)用了屬性”CustomerCode “。 Html.TextBoxFor(m => m.CustomerCode) 相同的方式,我們可以用“Html.CheckBox” 和 “Html.CheckBoxFor”創(chuàng)建checkbox。 MVC的路由選擇是什么?路由選擇功能幫你定義一個(gè)URL規(guī)則,映射URL到控制器。 舉一個(gè)例子,我們想讓用戶輸入“ http://localhost/View/ViewCustomer/ ”時(shí),它轉(zhuǎn)向到“Customer”控制器并且調(diào)用 routes.MapRoute( "View", // Route name "View/ViewCustomer/{id}", // URL with parameters new { controller = "Customer", action = "DisplayCustomer", id = UrlParameter.Optional }); // Parameter defaults 在哪里寫路由映射表?在 “ global.asax ” 文件。 我們可以映射多個(gè)URL到同一個(gè)動(dòng)作嗎?是的,可以。只需要添加多條不同Key名字的記錄,并且指定同樣的控制器和動(dòng)作。 使用hyperlink生成鏈接,如何從一個(gè)視圖鏈接到另一個(gè)視圖?使用 <%= Html.ActionLink("Home","Gotohome") %> 如何限制一個(gè)動(dòng)作的類型為GET或POST?我們可以給MVC的動(dòng)作一個(gè)HttpGet或HttpPost屬性去限制HTTP的類型。你可以看下面的代碼段,這個(gè) [HttpGet] public ViewResult DisplayCustomer(int id) { Customer objCustomer = Customers[id]; return View("DisplayCustomer",objCustomer); } 在MVC中如何保持Sessions?可以通過三種方式保持: tempdata, viewdata, 和viewbag。 tempdata, viewdata, 和 viewbag之間有什么不同?圖示: tempdata, viewdata, 和viewbag之間不同點(diǎn)
圖示: 動(dòng)態(tài)關(guān)鍵詞
下表是匯總:
MVC是的局部視圖是什么?局部視圖是一個(gè)可重復(fù)調(diào)用的視圖(和用戶控件一樣),它可以嵌入到視圖里面。例如:你的站點(diǎn)頁面有統(tǒng)一的菜單、頭部、尾部,如下圖所示: Figure: MVC中的局部視圖
如果你想在所有頁面重用菜單、頭部和尾部??梢詣?chuàng)建局部視圖,然后在主視圖中調(diào)用它們。 如何創(chuàng)建和調(diào)用局部視圖?點(diǎn)擊"Create partial view "復(fù)選框去添加局部視圖。 圖示: 創(chuàng)建局部視圖
局部視圖創(chuàng)建好后,在主視圖中使用 <body> <div> <% Html.RenderPartial("MyView"); %> </div> </body> MVC中如何做輸入驗(yàn)證?早期的MVC版本中使用數(shù)據(jù)注釋來做驗(yàn)證。除了注釋還可以利用數(shù)據(jù)模型的屬性標(biāo)簽。例如,下面的實(shí)例代碼中Customer類有一個(gè)屬性customercode。 這個(gè)CustomerCode屬性標(biāo)注了一個(gè)Required數(shù)據(jù)。如果不提供CustomerCode數(shù)據(jù),它將不能通過驗(yàn)證。 public class Customer { [Required(ErrorMessage="Customer code is required")] public string CustomerCode { set; get; } } 為了顯示驗(yàn)證錯(cuò)誤提示我們需要使用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屬性檢查數(shù)據(jù)是否正確。 public ActionResult PostCustomer(Customer obj) { if (ModelState.IsValid) { obj.Save(); return View("Thanks"); } else { return View("Customer"); } } 下面是一個(gè)顯示錯(cuò)誤信息的實(shí)例。 圖示: MVC中的驗(yàn)證
可以一次顯示所有的錯(cuò)誤信息嗎?可以。使用Html helper類中的ValidationSummary方法。 <%= Html.ValidationSummary() %> MVC中還有哪些注釋屬性用來驗(yàn)證? 如果你要去檢查字符的長度,你可以使用 [StringLength(160)] public string FirstName { get; set; } 如果你想使用注冊(cè)表達(dá)式,你可以使用 [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]public string Email { get; set; } 如果你想檢查數(shù)字是否在一個(gè)范圍內(nèi),你可以使用 [Range(10,25)]public int Age { get; set; } 有時(shí)你想比較兩個(gè)字段的值,我們可以使用 public string Password { get; set; }[Compare("Password")]public string ConfirmPass { get; set; } 如果你想拿到錯(cuò)誤詳情,你可以使用 var ErrMessage = ModelState["Email"].Errors[0].ErrorMessage; 如果你已經(jīng)創(chuàng)建好模型對(duì)象,你可以在Contronller中調(diào)用 TryUpdateModel(NewCustomer); 如果你想在Controller中添加錯(cuò)誤信息,你可以使用 ModelState.AddModelError("FirstName", "This is my server-side error."); 如何啟用客戶端驗(yàn)證?有兩個(gè)步驟:第一引用必須的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> 第二步去調(diào)用 <% Html.EnableClientValidation(); %> 什么是MVC中的Razor?它是一個(gè)輕量級(jí)的視圖引擎。MVC最初只有一個(gè)ASPX的視圖類型,直到MVC3才引進(jìn)了Razor 。 已經(jīng)有了ASPX,為什么還要Razor?相比ASPX,Razor是一個(gè)干凈的、輕量級(jí)的和語法更簡單。例如,ASPX去顯示時(shí)間: <%=DateTime.Now%> 在Razor中,只需要一行: @DateTime.Now Razor or ASPX,哪個(gè)更好?Razor更好,因?yàn)樗禽p量級(jí)的,并且語法簡單。 在MVC中如何做授權(quán)和認(rèn)證?在MVC中你可以使用Windows或Forms認(rèn)證。 在MVC中如何去執(zhí)行Windows認(rèn)證?你需要修改web.config文件,并設(shè)置驗(yàn)證模式為Windows。 <authentication mode="Windows"/> <authorization> <deny users="?"/> </authorization> 然后在controlle或action中,你可以使用 [Authorize(Users= @"WIN-3LI600MWLQN\Administrator")] public class StartController : Controller { // // GET: /Start/ [Authorize(Users = @"WIN-3LI600MWLQN\Administrator")] public ActionResult Index() { return View("MyView"); } } 在MVC中如何用表單認(rèn)證?表單認(rèn)證和ASP.NET的表單驗(yàn)證一樣。第一步是設(shè)置認(rèn)證模式為Forms。loginUrl是指向到controller,而不是一個(gè)頁面。 <authentication mode="Forms"> <forms loginUrl="~/Home/Login" timeout="2880"/> </authentication> 我們也需要?jiǎng)?chuàng)建一個(gè)controller,去驗(yàn)證用戶。如果驗(yàn)證通過,需要設(shè)置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"); } } 其它需要驗(yàn)證的action都需要加一個(gè) [Authorize] PublicActionResult Default() { return View(); } [Authorize] publicActionResult About() { return View(); } 在MVC中如何執(zhí)行AJAX?MVC中有兩種方式可以執(zhí)行AJAX:
下面是一個(gè)簡單的實(shí)例,它使用“AJAX”幫助執(zhí)行AJAX。在下面的代碼中,你可以使用Ajax.BeginForm創(chuàng)建了一個(gè)表單。這個(gè)表單調(diào)用了一個(gè)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點(diǎn)擊上做Ajax調(diào)用,你可以使用 圖示: 在MVC中執(zhí)行AJAX
如果你想創(chuàng)建一個(gè)AJAX異步hyperlink,它調(diào)用controller中的GetDate方法,代碼如下。一旦controller作出回應(yīng),這個(gè)數(shù)據(jù)會(huì)顯示在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調(diào)用的第二種方式是使用jQuery。下面的代碼你可以看到我們做了一個(gè)AJAX POST到 /MyAjax/getCustomer。 它 使用$.post。所有的邏輯代碼放在GetData函數(shù)中,你可以通過一個(gè)按鈕或者是鏈接點(diǎn)擊事件去調(diào)用它。 function GetData() { var url = "/MyAjax/getCustomer"; $.post(url, function (data) { $("#txtCustomerCode").val(data.CustomerCode); $("#txtCustomerName").val(data.CustomerName); } ) } 在AJAX中有幾種事件可以跟蹤?圖示: AJAX中的事件跟蹤
ActionResult 和 ViewResult有什么不同?
MVC有多少種不同類型的結(jié)果類型?注意: 很難去記住所有的12種類型。但是一些重要的你可以記住,例如: MVC中的12種結(jié)果類型,最主要的是ActionResult類,它是一個(gè)基礎(chǔ)類,它有11個(gè)子類型,如下:
MVC中的ActionFilters是什么?ActionFilters幫助你在MVC action執(zhí)行中或執(zhí)行后,執(zhí)行一些邏輯。 圖示: MVC中的ActionFilters。
Action filters通常用在下面的場(chǎng)景中:
你有兩種方式創(chuàng)建action filters:
創(chuàng)建內(nèi)聯(lián)action filter,我們需要執(zhí)行 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"); } } 內(nèi)聯(lián)Action filter的問題是不能跨Controler。我們可以轉(zhuǎn)換內(nèi)聯(lián)action filter到action filter屬性。創(chuàng)建action filter屬性,我們需要繼承 ActionFilterAttribute 和執(zhí)行 public class MyActionAttribute : ActionFilterAttribute , IActionFilter { void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) { Trace.WriteLine("Action Executed"); } void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { Trace.WriteLine("Action executing"); } } 之后我們可以在controller上使用這個(gè)屬性。你可以看下面的代碼: [MyActionAttribute] public class Default1Controller : Controller { public ActionResult Index(Customer obj) { return View(obj); } } MVC中可以創(chuàng)建自定義視圖引擎嗎?可以,在MVC中我們可以創(chuàng)建自己的自定義視圖引擎。創(chuàng)建自己的自定義視圖引擎需要跟隨下面三步: 我們將創(chuàng)建一個(gè)自定義視圖引擎,在視圖里用戶可以輸入一個(gè)命令,比如“<DateTime>”,它會(huì)顯示當(dāng)前的日期和時(shí)間。 步驟1 :我們需要?jiǎng)?chuàng)建一個(gè)類去執(zhí)行IView接口。我們應(yīng)該 在這個(gè)類的render函數(shù)中寫一些邏輯,指明如何渲染視圖。示例代碼如下: 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: 我們需要?jiǎng)?chuàng)建一個(gè)類,它繼承 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: 我們需要注冊(cè)自定義視圖到視圖集合。注冊(cè)自定義視圖引擎最適合的地方是global.aspx文件中的 protected void Application_Start() { // Step3 :- register this object in the view engine collection ViewEngines.Engines.Add(new MyViewEngineProvider()); ….. } 下面是一個(gè)實(shí)例,在自定義視圖的頂部中寫了一個(gè)定義好的命令。 圖示: MVC中的自定義視圖引擎
當(dāng)你調(diào)用視圖,你應(yīng)該能看見下面的輸出: 在MVC中如何返回JSON格式的結(jié)果?在MVC中,我們有 public JsonResult getCustomer() { Customer obj = new Customer(); obj.CustomerCode = "1001"; obj.CustomerName = "Shiv"; return Json(obj,JsonRequestBehavior.AllowGet); } 下面是上面代碼的JSON輸出: 什么是WebAPI?HTTP是最常用的協(xié)議。過去的很多年,瀏覽器是我們使用HTTP方式公開數(shù)據(jù)的首選客戶端。但是日新月異,客戶端發(fā)展到多種形式。我們需要使用HTTP方式傳遞數(shù)據(jù)給不同的客戶端,例如:移動(dòng)手機(jī)、Javascript,Windows應(yīng)用等等。 WebAPI是一個(gè)通過HTTP方式公開數(shù)據(jù)的技術(shù),它跟隨REST規(guī)則。 WCF SOAP 也做同樣的事情,它與WebAPI也有什么區(qū)別?
關(guān)于Web API, 你可以看我的另一篇翻譯:ASP.NET Web API詳解在MVC中我們?nèi)绾巫R(shí)別是PSOT還是GET調(diào)用?在控制器中識(shí)別POST或GET,我們可以使用 public ActionResult SomeAction() { if (Request.HttpMethod == "POST") { return View("SomePage"); } else { return View("SomeOtherPage"); } } 什么是MVC中的打包也壓縮?打包與壓縮幫助我們減少一個(gè)頁面的請(qǐng)求時(shí)間,從而提高頁面執(zhí)行性能。 打包如何搞高性能?我們的項(xiàng)目總是需要CSS和腳本文件。打包幫助你合并多個(gè)Javascript和css文件到單個(gè)文件,從而最小化多個(gè)請(qǐng)求到一個(gè)請(qǐng)求。 例如,包含下面的web請(qǐng)求到一個(gè)頁。這個(gè)頁面要求兩個(gè)Javascript文件, Javascript1.js 和 Javascript2.js 。 當(dāng)請(qǐng)求這個(gè)頁面時(shí),它要做三次請(qǐng)求:
如果頁面中有大量的javascript文件,這樣會(huì)降低性能。如果我們可以合并所有的JS文件到一個(gè)文件,只請(qǐng)求一個(gè),這將加增加性能。如下圖所示: MVC中如何執(zhí)行打包?打開 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; } } 一旦你合并了腳本到一個(gè)文件,你可以使用下面的代碼去調(diào)用它: <%= Scripts.Render("~/Scripts/MyScripts") %> 你將看到腳本請(qǐng)求被合并到一個(gè): 在debug模式下如何測(cè)試打包功能?如果你在debug模式下,你需要在bundleconfig.cs中設(shè)置 BundleTable.EnableOptimizations = true; 解釋壓縮,它是如何執(zhí)行的?壓縮功能通過移除空格、注釋等減少了腳本與CSS文件的大小。例如下面的代碼: // This is test var x = 0; x = x + 1; x = x * 2; 執(zhí)行壓縮后的Javascript代碼如下所示。 var x=0;x=x+1;x=x*2; |
|