Table 20-1: Tóm tắt chương Tạo một bộ view tuỳ chọn Thực hiện giao diện IViewEngine and IView 1 – 8 Tuỳ biến bộ view Razor Rút ra từ lớp RazorViewEngine 9 – 15 Định nghĩa vùng nội dụ
Trang 1Chapter 20: Views
Trong chương 17, bạn đã thấy cách mà các phương thức hoạt động có thẻ trả về các đối tượng
ActionResult Như các bạn đã học, hều hết sử dụng một cách thông thường kết qủa hành động là
ViewResult Như bạn thấy views đã được sử dụng trong nhiều ví dụ, vì vậy bạn biết mức độ mà họ làm Trong chương này, tôi tập trung và làm rõ ràng kiến thức đó Tôi bắt đàu bằng việc cho thấy cách mà MVC Framework xử lý ViewResults bằng việc sử dụng công cụ views, bao gồm chứng minh cách tạo một công
cụ views tuỳ chọn Kế tiếp, tôi sẽ mô tả kỹ thuật để làm việc hiệu quả hơn với Razor View Engine Khi đó tôi sẽ đề cập tới cách tạo và sử dụng view từng phần, các hành động con và các phần Razor (nó là tất cả bài viết thiết yếu dành cho sự phát triển MVC có hiệu quả Bảng 20-1 cung cấp bản tóm tắt dành cho chương này
Table 20-1: Tóm tắt chương
Tạo một bộ view tuỳ chọn Thực hiện giao diện IViewEngine
and IView
1 – 8
Tuỳ biến bộ view Razor Rút ra từ lớp RazorViewEngine 9 – 15
Định nghĩa vùng nội dụng cho sử dụng trong trình bày Sử dụng phần Razor 16
Áp dụng section trong trình bày Sử dụng các RenderSection và
RenderBody giúp đỡ
17 – 22
Định nghĩa các đoạn có thể tái sử dụng đánh dấu Sử dụng xem riêng từng phầm 23 – 26
Định nghĩa logic business có thể tái sử dụng Sử dụng các hành động con 27 – 29
Tạo một bộ view tuỳ chỉnh
Tôi sẽ đi sâu vào chi tiết cuối và tạo một bộ view tuỳ chọn Bạn không cần phải làm điều này cho hầu hết các dự án bởi vì các MVC Framework có công cụ xem Razor, có cú pháp tôi mô tả ở Chương 5 và trong
đó tôi đã được sử dụng cho tất cả các ví dụ cho đến nay trong cuốn sách này
Tip phiên bản cũ của MVC Framework hỗ trợ tạp view bằng cách sử dụng cùng một markup và công
cụ view như ASP.NET Web Forms, đó là lý do tại sao đôi khi bạn sẽ thấy tài liệu tham khảo để aspx file trong gỡ lỗi và các thông báo lỗi
Các giá trị trong việc tạo ra một công cụ view tùy chỉnh à để chứng minh làm thế nào các xử lý yêu cầu pipeline làm việc và hoàn thành kiến thức của bạn về cách MVC Framework hoạt động Điều này bao gồm sự hiểu biết chỉ có bao nhiêu quyền mà công cụ view được dịch trong ViewResult thành một đáp ứng cho client Công cụ View thực hiện giao diện IViewEngine, được thể hiện trong Listing 20-1
Listing 20-1 Giao diện IviewEngine rừ MVC Framework
namespace System.Web.Mvc {
public interface IViewEngine {
Trang 2ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
void ReleaseView(ControllerContext controllerContext, IView view);
}
}
Vai trò của công cụ View là dịch yêu cầu cho views vào đối tượng ViewEngineResult Hai phương pháp đầu tiên trong giao diện, FindView và FindPartialView, được thông qua các thông số mô tả các yêu cầu và các bộ điều khiển mà xử lý nó (một đối tượng ControllerContext), tên của view và layout của nó, và cho dù các công cụ View được cho phép sử dụng lại kết quả trước đó từ bộ nhớ cache của nó Những
phương pháp này được gọi khi một ViewResult đang được xử lý Phương pháp cuối cùng, ReleaseView, được gọi khi một lần xem là không còn cần thiết
Lưu ý: Sự hỗ trợ MVC Framework để công cụ view được thực hiện bởi lớp ControllerActionInvoker,
đó là việc thực hiện xây dựng trong giao diện IActionInvoker, như được mô tả trong Chương 17 Bạn sẽ không có quyền truy cập tự động tính năng công cụ view nếu bạn đã thực hiện hành động của riêng bạn invoker hay bộ điều khiển nhà máy trực tiếp từ IActionInvoker hoặc giao diện IControllerFactory
Lớp ViewEngineResult cho phép một công cụ view để đáp ứng với các MVC Framework khi view được yêu cầu Listing 20 – 2 cho thấy lớp ViewEngineResult
Listing 20 – 2: ViewEngineResult Class từ MVC Framework
}
public ViewEngineResult(IView view, IViewEngine viewEngine) {
if (view == null) { throw new ArgumentNullException("view");}
if (viewEngine == null) { throw new ArgumentNullException("viewEngine");}
View = view;
ViewEngine = viewEngine;
}
Trang 3public IEnumerable<string> SearchedLocations { get; private set; } public IView View { get; private set; }
public IViewEngine ViewEngine { get; private set; } }
Note: Bạn không một mình nếu bạn nghĩ rằng các lớp ViewEngineResult là một chút khó xử Bày tỏ các kết quả bằng cách sử dụng các phiên bản khác nhau của một lớp constructor là một phương pháp kỳ lạ và không thực sự phù hợp với phần còn lại của thiết kế MVC Framework Các khối nhà cuối cùng của hệ thống công
cụ view là giao diện IView, được thể hiện trong Listing 20-3
Listing 20 – 3: Các giao diện Iview từ MVC Framework
using System.IO;
namespace System.Web.Mvc {
public interface IView {
void Render(ViewContext viewContext, TextWriter writer);
}
}
Một thực hiện Iview ược truyền cho constructor của một đối tượng ViewEngineResult, sau đó được trả về từ phương thức công cụ xem Các MVC Framework sau đó gọi phương thức Render Các tham số ViewContext cung cấp thông tin về yêu cầu từ khách hàng và đầu ra từ các phương thức hành động Các tham số TextWriter là để viết ra cho client
Trang 4Các đối tượng ViewContext định nghĩa các thuộc tính mà cung cấp cho bạn truy cập vào thông tin về các yêu cầu và chi tiết về cách MVC Framework đã xử lý nó cho đến nay Tôi đã mô tả hữu hiệu nhất của các properties trong Bảng 20-2
Table 20 -2: Các thuộc tính ViewContext hữu dụng
Controller Trả về thực thi Icontroller mà xử lý các yêu cầu hiện tại
RequestContext Trả về chi tiết của các yêu cầu hiện tại
RouteData Trả về dữ liệu định tuyến cho các yêu cầu hiện tại
TempData Trả về dữ liệu tạm thời kết hợp với các yêu cầu
View Trả về việc thực hiện các giao diện IView đó sẽ xử lý yêu cầu
Rõ ràng, điều này sẽ được các lớp hiện tại nếu bạn đang tạo ra một thực hiện giao diện tùy chỉnh
ViewBag Trả về một đối tượng đại diện cho túi xem
ViewData Trả về một từ điển của dữ liệu mô hình view, mà cũng có chứa
các túi xem và dữ liệu meta cho mô hình Xem bảng 20-3 để biết chi tiết
Thú vị nhất của những thuộc tính là ViewData, mà trả về một đối tượng ViewDataDictionary Lớp ViewDataDictionary xác định một số đặc tính hữu ích cho phép truy xuất đến các mô hình view, túi view và siêu dữ liệu điểm mô hình Tôi đã mô tả hữu hiệu nhất của các thuộc tính trong Bảng 20-3
Key Trả về một tập hợp các giá trị quan trọng đối với các dữ liệu
trong từ điển, mà có thể được sử dụng để truy cập vào thuộc tính túi view
Model Trả về đối tượng mô hình view cho các yêu cầu
ModelMetadata Trả về một đối tượng ModelMetadata mà có thể được sử dụng
để phản ánh trên các loại mô hình ModelState Trả về thông tin về tình trạng của các mô hình, mà tôi mô tả chi
tiết trong Chương 25 Như tôi đã nói trước đó, cách đơn giản nhất để xem cách làm việc này như thế nào-IViewEngine, IView, và ViewEngineResult phù hợp với nhau, là để tạo ra một công cụ view Tôi sẽ tạo một công cụ xem đơn giản và trả về một loại view View này sẽ làm cho một kết quả chứ thông tin về các yêu cầu và xem dữ liệu được tạo ra bởi các phương thức hành động Cách tiếp cận này cho phép tôi chứng minh cách mà các công cụ view hoạt động mà không bị sa lầy vào việc phân tích xem mẫu view
Trang 5Chuẩn bị một dự án Example
Các dự án ví dụ cho phần này của chương được gọi là Views và tôi tạo ra nó bằng cách sử dụng mẫu Empty, kiểm tra các tuỳ chọn để thêm vào thư mục core MVC và tham khảo Tôi tạo ra bộ điều kiển Home, bạn có thể thấy trong Listing 20 – 4
Listing 20 – 4: Nội dung của HomeController.cs File
using System;
using System.Web.Mvc;
namespace Views.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
ViewBag.Message = "Hello, World";
ViewBag.Time = DateTime.Now.ToShortTimeString();
return View("DebugData");
} public ActionResult List() {
return View();
} }
}
Tôi đã không tạo bất kỳ view nào cho dự án vì tôi sẽ thực hiện môẹt công cụ xem tuỳ chọn hơn là dựa vào Razor
Tạo cộng Iview tuỳ chọn
Tôi sẽ bắt đầu bằng cách tạo ra một thực hiện cho giao diện Iview Tôi thêm một thư mục Infrastructure cho
dự án ví dụ và tạo một file lớp mới bên trong đó đc gọi là DebugDataView.cs, được thể hiện trong Listing
public class DebugDataView : IView {
public void Render(ViewContext viewContext, TextWriter writer) {
Write(writer, " -Routing Data -");
foreach (string key in viewContext.RouteData.Values.Keys) {
Trang 6Write(writer, "Key: {0}, Value: {1}", key, viewContext.RouteData.Values[key]);
} Write(writer, " -View Data -");
foreach (string key in viewContext.ViewData.Keys) {
Write(writer, "Key: {0}, Value: {1}", key, viewContext.ViewData[key]); }
} private void Write(TextWriter writer, string template, params object[] values) {
writer.Write(string.Format(template, values) + "<p/>");
} }
}
View này cho thấy sử dụng hai tham số cho phương thức Render ôi lấy các giá trị từ các
ViewContext và viết phản hồi cho khách hàng sử dụng các TextWriter Đầu tiên tôi viết ra các thông tin định tuyến dữ liệu và sau đó dữ liệu túi view
Tip: Các tính năng xem dữ liệu là một sự giữ lại từ các phiên bản trước đó của MVC Framework đã được phát hành trước khi C # có hỗ trợ cho các đối tượng năng động (mà tôi mô tả trong Chương 4) Xem
dữ liệu là một tiền chất ít linh hoạt để các túi view và không được sử dụng trực tiếp nữa, trừ khi viết hiện thực tùy chỉnh IView khi nó cung cấp dễ dàng truy cập đến các tài sản được xác định trên các đối tượng túi xem
Tạo một thực thi IviewEngine
Hãy nhớ rằng mục đích của công cụ view là tạo ra một đối tượng ViewEngineResult đó hoặc chứa những IView hoặc một danh sách những nơi họ tìm kiếm một cái nhìn phù hợp Bây giờ tôi có một thực hiện IView để làm việc, tôi có thể tạo ra các công cụ view Tôi đã thêm một tập tin gọi là lớp
DebugDataViewEngine.cs trong thư mục Infrastructure, các nội dung trong đó được hiển thị trong Listinh
20 – 6
Listing 20 – 6: Nội dung của tập tin DebugDataViewEngine.cs
using System.Web.Mvc;
namespace Views.Infrastructure {
public class DebugDataViewEngine : IViewEngine {
public ViewEngineResult FindView(ControllerContext controllerContext,
string viewName, string masterName, bool useCache) {
if (viewName == "DebugData") {
return new ViewEngineResult(new DebugDataView(), this);
Trang 7} else {
return new ViewEngineResult(new string[]
{ "No view (Debug Data View Engine)" });
} }
public ViewEngineResult FindPartialView(ControllerContext controllerContext,
string partialViewName, bool useCache) { return new ViewEngineResult(new string[]
{ "No view (Debug Data View Engine)" });
} public void ReleaseView(ControllerContext controllerContext, Iview view) { // do nothing
} }
DebugData, tôi trả về một ViewEngineResult, như thế này:
Trang 8thức ReleaseView, bởi vì không có nguồn tài nguyên mà tôi cần giải phóng trong việc thực hiện tùy chỉnh IView, đó là mục đích thông thường của phương pháp này
Đăng ký một công cụ view tuỳ chọn
Tôi đăng ký công cụ view tuỳ chọng trong phương thức Application_Start của Global.asax, như thể hiện trong Listing 20 – 7
Listing 20 – 7: Đăng ký một Công cụ View Tuỳ chọn sử sung Global.asax
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Add(new DebugDataViewEngine());
} }
}
Các bộ sưu tập static ViewEngine.Engines chứa tập hợp các công cụ xem được cài đặt trong ứng dụng MVC Framework hỗ trợ ý tưởng của một số công cụ được cài đặt trong một ứng dụng duy nhất Khi một ViewResult đang được xử lý, các hành động Invoker có được các bộ cài đặt công cụ view và được gọi
là phương thức FindView lần lượt
Các hành động Invoker ngừng gọi các phương thức FindView ngay khi nó nhận được đối tượng ViewEngineResult mà có chứa Iview Điều này có nghĩa là thứ tự mà các công cụ được thêm vào bộ
ViewEngines.Engines là đáng kể nếu hai hay nhiều công cụ có thể phục vụ yêu cầu cho cùng tên view Nếu bạn muốn xem view của bạn được ưu tiên, sau đó bạn cần chèn nó vào đầu của bộ sưu tập như thế này:
ViewEngines.Engines.Insert(0, new DebugDataViewEngine());
Trang 9
Kiểm thử Công cụ View
Tôi bây giờ ở một vị trí để thử nghiệm các công cụ view tùy chỉnh Khi ứng dụng được bắt đầu, trình duyệt sẽ tự động điều hướng đến các URL gốc cho các dự án, sẽ được ánh xạ tới các hành động Index trong
bộ điều khiển Home Các phương thức hành động sử dụng các phương thức View để trả về một ViewResult
mà xác định DebugData view Bạn có thể xem kết quả của điều này trong hình 20-1
Hình 20 – 1: Sử dụng công cụ view tuỳ chon Đây là kết quả của phương pháp FindView được gọi cho môt view mà tôi có thể xử lý Nếu bạn điều hướng đến /Home/List URL, MVC Framework sẽ gọi phương thức Danh sách hành động, trong đó kêu gọi các Xem phương thức để yêu cầu xem mặc định của nó, mà không phải là một trong đó là hỗ trợ Bạn có thể xem kết quả trong hình 20-2
Hình 20 – 2: Yêu cầu một view không được hỗ trợ Bạn có thể thấy rằng thông điệp của tôi được ghi nhận là một trong những địa điểm đã được tìm kiếm cho một view Chú ý rằng Razor và ASPX view xuất hiện trên danh sách là tốt Điều này là do những công
cụ xem vẫn đang được sử dụng Nếu tôi muốn đảm bảo rằng chỉ có công cụ view tùy chỉnh của tôi đang sử
Trang 10dụng, sau đó tôi phải gọi phương thức Clear trước khi tôi đăng ký công cụ của tôi trong tập tin Global.asax, như thể hiện trong Listing 20-8
Listing 20 – 8: Loại bỏ công cụ view khác trong Global.asax File
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {
Trang 11Làm việc với Công cụ Razor
Trong phần trước, tôi đã có thể tạo ra một công cụ view tùy chỉnh bằng cách thực hiện chỉ hai giao diện Phải thừa nhận rằng, tôi đã kết thúc với một cái gì đó đơn giản mà tạo ra view xấu xí, nhưng bạn thấy làm thế nào các khái niệm về MVC mở rộng tiếp tục suốt đường ống xử lý yêu cầu
Sự phức tạp trong một công cụ view xuất phát từ hệ thống mẫu view mà bao gồm những đoạn mã và
bố trí hỗ trợ, và được biên dịch để tối ưu hóa hiệu suất Tôi đã không làm bất kỳ điều nào trong công cụ view tuỳ chọn đơn giản và không có nhiều điều cần làm, bởi vì xây tích hợp trong công cụ Razor đảm bảo tất cả điều đó cho tôi Các chức năng mà hầu như tất cả các ứng dụng MVC đòi hỏi có sẵn trong Razor Chỉ
có một số nhỏ vanishingly của dự án cần đi đến rắc dối của việc tạo ra một công cụ xem tuỳ chọn Tôi đưa cho bạn một mẩu thử trong cú pháp Razor trong Chương 5 Trong chương này, tôi sẽ cho bạn thấy cách sử dụng các tính năng để tạo ra và đưa ra view Razor Bạn sẽ tìm hiểu làm thế nào để tuỳ chỉnh công cụ Razor
Chuẩn bị một dự án ví dụ
Đối với phần này của chương, tôi đã tạo ra một dự án MVC mới bằng cách sử dụng tùy chọn mẫu Empty, kiểm tra các tùy chọn để thêm các thư mục core MVC và tham khảo Tôi gọi là dự án
WorkingWithRazor và tôi đã thêm một bộ điều khiển Home, được thể hiện trong Listing 20 – 9
Listing 20 – 9: Nội dung của tập tin HomeController.cs
using System.Web.Mvc;
namespace WorkingWithRazor.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
string[] names = { "Apple", "Orange", "Pear" };
return View(names);
} }
his is a list of fruit names:
@foreach (string name in Model) {
<span><b>@name</b></span>
} Un
Trang 12Việc hiểu Razor View Rendering The Razor View Engine iên soạn các quan điểm trong các ứng dụng của bạn để cải thiện hiệu suất Các views được dịch sáng lớp C# và sau đó được biên soạn, đó là lý do tại sao bạn có thể bao gồm fragments C # code để dễ dàng Đó là bài học để xem xét mã nguồn mà Razor view tạo ra, bởi vì nó giúp đưa ra nhiều tính năng trong ngữ cảnh
Các views trong ứng dụng MVC công được biên dịch cho tới khi ứng dụng đó được bật lên, như vạy
sể xem các lớp được tạo ra bởi Razor, bạn cần phải khởi động ứng dụng và điều hướng đến /Home/Index action Các yêu cầu ban đầu đến ứng dụng MVC kích hoạt các tiến trình biên dịch cho tất cả view Bạn có thể thấy kể quả của các yêu cầu trong hình 20 – 4
Hình 20 – 4 Các đầu ra từ phương thức Index action trên bộ điều kiểu Home
Một cách thuận tiện, các lớp được tạo ra từ các tập tin view được ghi vào đĩa như file code C# và sau đó biên dịch, ó nghĩa là bạn có thể xem các báo cáo C# mà đại diện cho một view Bạn có thể tìm thấy các tập tin được tạo ra trong C:\Users\<yourLoginName>\AppData\Local\Temp\Temporary ASP.NET Files trên Win7 và Win8
Việc tìn kiếm các tập tin code được tạo ra cho một view cụ thể đòi hỏi một chút poking xung quanh Thường có một số thư mục lớn với tên khó hiểu, và tên của tập tin cs không tương ứng với tên của lớp chúng ta chứa Như một ví dụ, tôi thấy các lớp tạo ra một view trong Listing 20 – 10 trong một tập tin là App_Web_ihpp0d0l.0.cs trong oot\7bbfc2bc\bd7485cd Tôi đã dọn dẹp các lớp từ hệ thống tạo cho nó dễ dàng hơn để đọc Như thể hiện trong Listing 20-11
Listing 20-11 Các Generated C # Class cho một Razor View
Trang 13public override void Execute() {
ViewBag.Title = "Index";
WriteLiteral("\r\n\r\nThis is a list of fruit names:\r\n\r\n");
foreach (string name in Model) {
WriteLiteral(" <span><b>");
Write(name);
WriteLiteral("</b></span>\r\n");
} }
}
}
Đầu tiên, lưu ý rằng các lớp có nguồn gốc từ WebViewPage <T>, trong đó T là các loại mô hình: WebViewPage <string []> ví dụ này Đây là cách mà views được xử lý một cách mạnh mẽ Cũng cần lưu ý tên của các lớp đã được tạo ra: _Page_Views_Home_Index_cshtml Bạn có thể thấy đường dẫn của file view đã được mã hóa trong các tên lớp Đây là cách Razor ánh xạ yêu cầu cho các view vào trường hợp của các lớp được biên dịch
Trong phương thức Execute, bạn có thể thấy các báo cáo và các yếu tố trong giao diện đã được xử lý Những đoạn code mà tôi bắt đầu bằng ký hiệu @ được thể hiện trực tiếp như câu lệnh C# Các các phần tử HTML được xử lý bằng phương pháp WriteLiteral, trong đó viết nội dung của các thông số để kết quả là chúng được đưa ra Điều này trái ngược với phương thức Write, được sử dụng cho C # biến và mã hóa các giá trị chuỗi ký tự để bảo đảm an toàn cho sử dụng trong một trang HTML
Cả Write và phương thức WriteLiteral viết viết nội dung vào một đối tượng TextWriter Đây là cùng một đối tượng được truyền cho phương thức IView.Render, mà bạn nhìn thấy ở đầu chương Mục tiêu của một view Razor được biên dịch là để tạo ra các nội dung tĩnh và động và gửi nó cho khách hàng thông qua các TextWriter Điều này rất hữu ích để giữ ghi nhớ khi tôi chuyển sang phương thức trợ giúp HTML sau này trong chương sau
Trang 14Cấu hình View Search Locations
The Razor View Engine tuân theo một quy ước tiêu chuẩn khi tìm kiếm một view Ví dụ, nếu bạn yêu cầu xem Index kết hợp với bộ điều khiển Home, Razor sẽ thông qua danh sách của views:
Bạn có thể thay đổi các tập tin view, cái mà Razor tìm kiếm bằng cách tạo ra một lớp con của
RazorViewEngine Lớp này là Razor IviewEngine implementation Nó được xây dựng dựa trên một loạt các lớp cơ sở mà xác định một tập hợp các thuộc tính có xác định xem các tập tin được tìm kiếm Những đặc tính này được mô tả trong Table 20 – 4
Table 20 – 4: Thuộc tính Razor View Engine Search
ViewLocationFormats
MasterLocationFormats
PartialViewLocationFormats
Các địa điểm để tìm view, view 1 phần, layout
∼/Views/{1}/{0}.cshtml,
∼/Views/{1}/{0}.vbhtml,
∼/Views/Shared/{0}.cshtml,
∼/Views/Shared/{0}.vbhtml AreaViewLocationFormats
AreaMasterLocationFormats
AreaPartialViewLocationFormats
Các địa điểm để tìm view, view 1 phần, layout cho vùng
∼/Areas/{2}/Views/{1}/{0}.cshtml,
∼/Areas/{2}/Views/{1}/{0}.vbhtml,
∼/Areas/{2}/Views/Shared/{0}.cshtml,
∼/Areas/{2}/Views/Shared/{0}.vbhtml
Các tính chất này có trước sự ra đời của Razor, mà tại sao mỗi bộ ba thuộc tính có giá trị như nhau Mỗi thuộc tính là một mảng các chuỗi, được thể hiện bằng các ký hiệu định dạng chuỗi composite Sau đây
là các giá trị tham số tương ứng với các placeholders:
{0} đại diện cho tên của view
{1} đại diện cho tên của bộ điều khiển
Trang 15{2} đại diện cho tên của khu vực
Để thay đổi vị trí tìm kiếm, bạn tạo ra một lớp mới mà có nguồn gốc từ RazorViewEngine và thay đổi các giá trị cho một hoặc nhiều tính chất mô tả trong Bảng 20-4
Để chứng minh làm thế nào để thay đổi vị trí được tìm kiếm, tôi đã thêm một thư mục Infrastructure cho dự án và tạo ra một tập tin gọi là lớp CustomLocationViewEngine.cs, được thể hiện trong Listing 20-12
Listing 20-12 Nội dung của tập tin CustomLocationViewEngine.cs
}
Tôi đã thiết lập một giá trị mới cho ViewLocationFormats Các mảng mới có chứa các mục cho các file cshtml Ngoài ra, tôi đã thay đổi vị trí tôi tìm kiếm quan điểm chung là Views/Common, hơn nữa là Views/Shared Tôi đăng ký các công cụ xem có nguồn gốc sử dụng các bộ ViewEngines.Engines trong phương pháp Application_Start của Global.asax, như thể hiện trong Listing20-13
Listing 20-13 Đăng ký Custom View Engine trong File Global.asax
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {