ไฟล์โครงร่าง _ViewStart.cshtml เชื่อมโยงอยู่ที่ไหนและอย่างไร


199

นี่คือ About.cshtml จากเทมเพลต MVC 3 เริ่มต้น:

@{
    ViewBag.Title = "About Us";
}

<h2>About</h2>
<p>
     Put content here.
</p>

ฉันคาดหวังว่าการอ้างอิงไปยังไฟล์ _ViewStart จะพบได้ในAbout.cshtmlแต่ไม่ชัดเจน

ผมมองในglobal.asaxและweb.configแต่ฉันไม่สามารถหาวิธีการที่About.cshtmlไฟล์ "ที่เชื่อมโยง" กับรูปแบบจากแฟ้ม _ViewStart

ทุกอย่างทำงานได้ตามที่คาดหวังฉันแค่อยากรู้ว่าเกิดอะไรขึ้นภายใต้ประทุน ...

คำตอบ:


237

จากบล็อกของ ScottGu :

เริ่มต้นด้วยการเปิดตัว ASP.NET MVC 3 Beta ตอนนี้คุณสามารถเพิ่มไฟล์ชื่อ _ViewStart.cshtml (หรือ _ViewStart.vbhtml สำหรับ VB) ภายใต้โฟลเดอร์ \ Views ของโครงการของคุณ:

ไฟล์ _ViewStart สามารถใช้เพื่อกำหนดรหัสมุมมองทั่วไปที่คุณต้องการเรียกใช้เมื่อเริ่มต้นการเรนเดอร์แต่ละมุมมอง ตัวอย่างเช่นเราสามารถเขียนโค้ดในไฟล์ _ViewStart.cshtml ของเราเพื่อตั้งค่าคุณสมบัติโครงร่างสำหรับแต่ละมุมมองโดยทางโปรแกรมเป็นไฟล์ SiteLayout.cshtml โดยค่าเริ่มต้น:

เนื่องจากรหัสนี้ทำงานเมื่อเริ่มต้นแต่ละมุมมองเราไม่จำเป็นต้องกำหนดเค้าโครงในไฟล์มุมมองแต่ละไฟล์ของเราอีกต่อไป (ยกเว้นถ้าเราต้องการแทนที่ค่าเริ่มต้นด้านบน)

สำคัญ: เนื่องจาก _ViewStart.cshtml ช่วยให้เราสามารถเขียนโค้ดเราสามารถเลือกให้ตรรกะการเลือกเค้าโครงของเราสมบูรณ์ยิ่งขึ้นกว่าชุดคุณสมบัติพื้นฐาน ตัวอย่างเช่น: เราสามารถเปลี่ยนแปลงแม่แบบเค้าโครงที่เราใช้ขึ้นอยู่กับประเภทของอุปกรณ์ที่เข้าถึงไซต์ - และมีเค้าโครงโทรศัพท์หรือแท็บเล็ตที่ปรับให้เหมาะสมที่สุดสำหรับอุปกรณ์เหล่านั้นและเค้าโครงที่ปรับให้เหมาะกับพีซี / แล็ปท็อป หรือถ้าเรากำลังสร้างระบบ CMS หรือแอพที่ใช้ร่วมกันทั่วไปที่ใช้กับลูกค้าหลายรายเราสามารถเลือกเลย์เอาต์ที่แตกต่างกันเพื่อใช้ขึ้นอยู่กับลูกค้า (หรือบทบาทของพวกเขา) เมื่อเข้าสู่เว็บไซต์

สิ่งนี้ช่วยให้ UI มีความยืดหยุ่นมาก นอกจากนี้ยังช่วยให้คุณสามารถเขียนตรรกะการดูได้ง่ายขึ้นหนึ่งครั้งและหลีกเลี่ยงการทำซ้ำในหลาย ๆ ที่

ดูสิ่งนี้ด้วย


14
ดังนั้นคุณลักษณะ "hardcoded" ของ MVC3 มากหรือน้อย ฉันไม่ต้องการเปลี่ยนเป็นหน้า "เริ่มต้น" อีกหน้าอยากรู้ว่ามันถูกตั้งค่าอย่างไร ขอบคุณสำหรับการคัดสรรทุกอย่าง :)
Kman

2
Kman- Hardcoded ตามแบบแผน (เลือก 'ที่จับ' อีกอันที่นี่ :)) - ใช่แน่นอน ดีใจที่ได้ล้างหมอก
จิมโทลลัน

ไม่ใช่แค่ในโฟลเดอร์ "Views" ที่คุณอาจต้องการ หากคุณเพิ่ม RazorViewEngine แบบกำหนดเองเพื่อจัดระเบียบมุมมองลงในโฟลเดอร์อื่นคุณต้องรวมไฟล์ไว้ในรูทของโฟลเดอร์มุมมองทางเลือกเหล่านั้นด้วย ตัวอย่างเช่นผมย้ายทั้งหมดมุมมองแม่แบบ Inspinia ViewLocationFormats = ViewLocationFormats.Union(new string[] { "~/Inspinia/ExampleViews/{1}/{0}.cshtml" }).ToArray();ลงในโฟลเดอร์และวิ่งไปนี้ในเครื่องมือมุมมอง เป็นผลให้ฉันต้องเพิ่มสำเนาของไฟล์ _ViewStart.cshtml ของฉันไปที่ "~ / Inspinia / ExampleViews" มิฉะนั้นจะไม่ได้รับและไม่มีการตั้งค่าเค้าโครง
Triynko

2
หากโฟลเดอร์ Views ของคุณมีโฟลเดอร์ย่อยคุณสามารถใส่ a _ViewStartในโฟลเดอร์ย่อยแต่ละโฟลเดอร์ที่จะเชื่อมโยงไปยังมุมมองในโฟลเดอร์ย่อยนั้นได้หรือไม่?
toddmo

35

โดยทั่วไปแล้วความสามารถของกรอบ MVC ในการ "รู้" เกี่ยวกับ _Viewstart.cshtml นี้เรียกว่า"การเข้ารหัสตามแบบแผน"

Convention over configuration (เรียกอีกอย่างว่าการเขียนรหัสโดยอนุสัญญา) เป็นกระบวนทัศน์การออกแบบซอฟต์แวร์ที่พยายามลดจำนวนการตัดสินใจที่นักพัฒนาจำเป็นต้องทำเพิ่มความเรียบง่าย แต่ไม่จำเป็นต้องสูญเสียความยืดหยุ่น วลีนี้หมายถึงนักพัฒนาจำเป็นต้องระบุแง่มุมที่แปลกใหม่ของแอปพลิเคชัน ตัวอย่างเช่นหากมีการลดราคาในชั้นเรียนโมเดลตารางที่สอดคล้องกันในฐานข้อมูลจะถูกเรียกว่า "ยอดขาย" โดยค่าเริ่มต้น เฉพาะในกรณีที่มีการเบี่ยงเบนจากการประชุมนี้เช่นการเรียกตาราง“ products_sold” ผู้นั้นจำเป็นต้องเขียนโค้ดเกี่ยวกับชื่อเหล่านี้

วิกิพีเดีย

ไม่มีเวทมนต์สำหรับมัน มันเพิ่งถูกเขียนลงใน codebase หลักของเฟรมเวิร์ก MVC และดังนั้นจึงเป็นสิ่งที่ MVC "รู้" เกี่ยวกับ นั่นเป็นสาเหตุที่คุณไม่พบมันในไฟล์. config หรือที่อื่น เป็นจริงในรหัส MVC อย่างไรก็ตามคุณสามารถแทนที่การเปลี่ยนแปลงหรือยกเลิกอนุสัญญาเหล่านี้ได้


13
ถ้า MVC รู้เรื่องนี้เหตุใด Visual Studio จึงไม่รู้จักและชี้ประเด็นนี้ให้ฉัน หากการเข้ารหัสโดยการประชุมหมายความว่าสิ่งต่าง ๆ ทำงานได้นานเท่าที่คุณจะไม่ทำลายการประชุมแบบที่มันแย่ ...
Arne Evertsson

การไม่ทำลายการประชุมเป็นประเด็น AKAIK Ruby on Rails ก็ทำตามกระบวนทัศน์นี้เช่นกัน
Umar Farooq Khawaja

+1 Raif ไม่มีจุดใดในการปกป้อง "การเข้ารหัสตามแบบแผน" ที่บันทึกไว้ไม่ดี ฉันสามารถพูดได้ว่าเกี่ยวกับรหัสย้อนหลังของฉัน "อะไรนะคุณไม่คาดหวังว่ามันจะพังเมื่อมันอายุ 33 ปีทุกคนรู้ว่าคุณข้าม 33" น่าเสียดายที่ช่องว่างเอกสารสำหรับ ASP.NET MVC นั้นใหญ่มาก เอกสาร MS เท่านั้นที่สร้างขึ้นโดยอัตโนมัติโดยไม่มีการสรุปแหล่งที่มาภายใน
แชนนอน

6
Convention over configuration ไม่ได้หมายความว่าคุณจะไม่สามารถเปลี่ยนแปลงได้ ควรมีการกำหนดค่าที่สามารถระบุชื่อและที่ตั้งของไฟล์นั้นได้ อาจจะเป็นอย่างดี แต่ใครจะรู้ว่ามันคืออะไร ผู้คนใช้คำว่า "อนุสัญญามากกว่าการกำหนดค่า" เพื่อปิดบังการตัดสินใจที่ไม่ดีในโค๊ดเบสและมันทำให้ฉันโกรธในขณะที่คนที่แต่งตัวประหลาดมาตามความจริงเพื่อรักษาระเบียบที่ไม่ดีของเอกสารว่า "ใช้ได้" (แต่ พระเจ้าห้ามไม่ให้คุณเปลี่ยนแปลงอะไร - คุณจะใช้เวลาหลายชั่วโมงในการหาวิธีที่คุณทำลายทุกอย่าง)
Robert C. Barth

3
@AidenStrydom ฉันไม่เห็นด้วย คำตอบที่ยอมรับได้จริงจะบอกวิธีใช้ _ViewStart คำตอบนี้พูดถึงแนวคิดการออกแบบ ฉันมาที่นี่เพื่อรับข้อมูลเกี่ยวกับ _ViewStart ไม่ใช่ข้อมูลเกี่ยวกับสาเหตุที่ Visual Studio ไม่บอกอะไรเกี่ยวกับ _ViewStart
มิลลี่สมิ ธ

23

อีกความคิดหนึ่ง

หากคุณต้องการให้cshtmlไฟล์ของคุณเป็นแม่แบบทั่วไปคุณสามารถทำได้ด้วยวิธีนี้

ภายในของ_viewstart.cshtmlคุณคุณสามารถพูดถึงcshtmlไฟล์ทั่วไปของคุณ

@{Layout = "~/Views/Shared/_Layout.cshtml";}

14

ซอร์สโค้ดเป็นที่ที่ดีกว่าในการค้นหาสิ่งนี้มากกว่าเอกสาร

อ้างอิงรหัส MVC 6จาก Github เรามีไฟล์ที่น่าสนใจเล็กน้อย

---- ปรับปรุง ----

เนื่องจากการเปลี่ยนแปลงโครงสร้างแหล่งที่มาข้อมูลเกี่ยวกับวิธีการรวบรวมหน้าเว็บเริ่มต้นที่สามารถพบได้ในRazorViewEngine.csมองหาฟังก์ชั่น "GetViewStartPages"

---- / อัปเดต ----

เพื่อที่จะตอบว่าพวกเขาเข้ามาเล่นอย่างไรให้ดูที่RazorViewซึ่งฉันเชื่อว่า (เพราะ IView) เชื่อมโยงกับ MVC ไปป์ไลน์ ไฟล์นี้มีเมธอด RenderAsync ที่ถูกเรียกจากไปป์ไลน์ MVC เพื่อแสดงมุมมองที่ร้องขอ

RenderAsync ทำการโทรไปยัง RenderPage และ RenderLayout (หมายเหตุคำสั่งซื้อ) RenderPage ก่อนทำการโทรเพื่อจัดการกับไฟล์ viewstart (พหูพจน์โน้ต, อาจมีไฟล์ _viewstart มากกว่าหนึ่งไฟล์)

ดังนั้นข้อมูลที่คุณค้นหาสามารถหาได้จากฟังก์ชันRenderViewStartAsyncในไฟล์RazorView.csภายใต้ Microsoft.AspNet.Mvc.Razor namespace


7

นี่อาจเพิ่มข้อมูล addt'l ให้กับคำถามนี้ทันที (2016 ala MVC4, MVC5)

เอ็นจิ้นมีดโกนค้นหาและเรียกใช้รหัสใน_ViewStart.cshtmlก่อนรหัสอื่นใดซึ่งอยู่ในไดเรกทอรีเดียวกันหรือไดเรกทอรีย่อยที่พบ_ViewStart.cshtml

มุมมองใด ๆ สามารถแทนที่คุณสมบัติเค้าโครงหรือค่าใด ๆ

แค่คิดว่าฉันอาจเพิ่มข้อมูลอีกเล็กน้อยเพื่อแสดงให้คุณเห็นว่าทำไมมันถึง _ViewStart

ถ้าคุณได้รับILSpyและตรวจสอบรหัสใน RazorViewEngine (System.Web.Mvc.dll) คุณจะเห็นว่ารหัสนั้นอ้างอิงชื่อนั้น

_ViewStart ใน System.Web.Mvc.dll

คุณจะเห็นว่า RazorViewEngine ค้นหาไฟล์ที่มีชื่อนั้น:

รหัส razorviewengine

RazorViewEngine.ViewStartFileName = "_ViewStart";

3
นี่คือสิ่งที่ฉันกำลังมองหาฉันเกลียด "ไม่ทราบ" สิ่งที่เกิดขึ้นในโครงการของฉันเพราะฉันยังทำแม่แบบของฉันสำหรับ VS และไฟล์ที่เพิ่งออกมาจากอากาศนี้เป็นเรื่องยากที่จะเข้าใจ
เซบาสเตียน 506563

1

หากคุณต้องการมีเลย์เอาต์ทั่วไปสำหรับเพจของคุณคุณจำเป็นต้องกำหนดเลย์เอาต์ทั่วไปและเชื่อมโยงมุมมองกับเลย์เอาต์เราต้องตั้งค่าคุณสมบัติเลย์เอาต์ในทุก ๆ มุมมองซึ่งเป็นการละเมิดหลักการ DRY (อย่าซ้ำตัวเอง) สำหรับ. Net Framework นี้ได้จัดเตรียมไฟล์ "_ViewStart.cshtml" ไว้ในโฟลเดอร์มุมมอง เราวางข้อมูลเลย์เอาต์ในไฟล์ "_ViewStart.cshtml" และทุกมุมมองโดยค่าเริ่มต้นจะใช้ข้อมูลเลย์เอาต์นี้ หากคุณต้องการให้ข้อมูลเลย์เอาต์ที่แตกต่างกันลองสมมติว่าเป็นมุมมองโฮมของคุณคุณสามารถสร้าง "_ViewStart.cshtml" ใหม่โดยอ้างอิงกับโครงร่างนั้นและวางไว้ในโฟลเดอร์ "Home View"


1

คำตอบสั้น ๆ คือ : ViewStarts เริ่มต้นก่อนเมื่อมีการแสดงผลมุมมองใด ๆ เรื่องยาวอยู่ด้านล่าง:

เรื่องราวของการสร้างไฟล์มุมมองเดียว:

  1. ViewStart ถูกรวมเข้ากับ ViewImports และดำเนินการเป็นไฟล์เดียว โปรดทราบว่า ViewImports จะถูกรวมเข้ากับไฟล์ cshtml ใด ๆ รวมถึงไฟล์ ViewStart เสมอ โดยมีวัตถุประสงค์คือการใช้งบ @ ใช้นามธรรมและคำสั่งทั่วไปอื่น ๆ
  2. เอาต์พุตของ ViewStart (เช่น Layout และ ViewData) จะมีให้สำหรับไฟล์ View ที่ระบุ
  3. ภายในไฟล์มุมมองหากตัวแปรเค้าโครงเป็น / กลายเป็นโมฆะเนื้อความของมุมมองจะถูกเรนเดอร์และเอาต์พุตสุดท้ายจะถูกส่งไปยังผู้ใช้
  4. หากตัวแปร Layout เป็น / ไม่เป็นโมฆะการดำเนินการจะถูกย้ายไปยังไฟล์เลย์เอาต์ซึ่งจะถูกรวมเข้ากับ ViewImports เป็นไฟล์เดียวจากนั้นที่คำสั่ง @RenderBody () ภายในการดำเนินการของไฟล์เลย์เอาต์จะถูกย้ายกลับไปที่ไฟล์มุมมอง ซึ่งถูกผสานเข้ากับ ViewImports อีกครั้งและเอาต์พุตถูกรวมเข้ากับไฟล์เลย์เอาต์ที่ตำแหน่งของ @RenderBody () และสุดท้ายผลลัพธ์ก็จะถูกส่งไปยังผู้ใช้

สิ่งนี้ทำให้คุณตระหนักถึงสิ่งที่เกิดขึ้นจริงภายในความลึกลับที่ไม่รู้จักในวงจรชีวิตของโปรแกรมของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.