MVC Razor แบบไดนามิก 'object' ไม่มีคำจำกัดความสำหรับ 'PropertyName'


106

ใช้ MVC 3 กับ Razor view engine ฉันมีมุมมองนี้:

@model dynamic
@{
    var products = (List<ListItemBaseModel>)Model.Products;
    var threshold = (int)(Model.Threshold ?? 1);
    var id = Guid.NewGuid().ToString();
}

เรียกจากมุมมองอื่นโดยใช้รหัสนี้:

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })

ในมุมมองทั้งสองเมื่อฉันดีบักและดูโมเดลดูเหมือนว่าจะมีวัตถุที่ถูกต้อง เมื่อฉันรันโค้ดฉันได้รับข้อผิดพลาดในบรรทัด "var products =" ว่า:

'object' ไม่มีคำจำกัดความสำหรับ 'Products'

ใครช่วยอธิบายให้ฉันฟังได้ไหมว่าทำไมฉันถึงได้รับข้อผิดพลาดนั้น อีกครั้งเมื่อฉันดู Model object ในโหมด debugging มันก็ดูดี (มี 2 คุณสมบัติ: Products and Threshold)


2
การทำซ้ำที่เป็นไปได้ของประเภท Dynamic Anonymous ใน Razor ทำให้ RuntimeBinderException
Rune FS

คำตอบ:


150

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

// error
return View(new { Foo = 1, Bar = "test" });

// worked
return View(new TestClass { Foo = 1, Bar = "test" });

แก้ไข # 1:

ตามข้อมูลของDavid Ebboคุณไม่สามารถส่งประเภทที่ไม่ระบุตัวตนไปยังมุมมองที่พิมพ์แบบไดนามิกได้เนื่องจากประเภทที่ไม่ระบุตัวตนถูกรวบรวมเป็นinternalไฟล์. เนื่องจากมุมมอง CSHTML ถูกคอมไพล์เป็นแอสเซมบลีแยกต่างหากจึงไม่สามารถเข้าถึงคุณสมบัติของชนิดที่ไม่ระบุชื่อได้

แก้ไข # 2:

David Ebbo ได้แก้ไขโพสต์ของเขาด้วยคำชี้แจงนี้:

หมายเหตุ (22 ธันวาคม 2554): ตอนนี้ MVC 3 รองรับไดนามิกโดยตรงแล้วเทคนิคด้านล่างก็ไม่จำเป็นอีกต่อไป โพสต์นี้เป็นสิ่งที่นำไปสู่การรวมคุณลักษณะนี้เข้ากับ MVC!


1
การแก้ไขเป็นสิ่งที่ดีที่ได้ทราบ ฉันเพิ่งมีปัญหาเดียวกันและไม่เข้าใจ WTF ที่นั่น ขอบคุณสำหรับคำอธิบาย
Yanick Rochon

18
แก้ไข # 2 แนะนำว่าตอนนี้ (MVC> 3) สามารถทำบรรทัดเพื่อทำเครื่องหมาย "ข้อผิดพลาด" ได้หรือไม่ return View(new { Foo = 1, Bar = "test" });เหรอ? เพราะฉันใช้ MVC 4 และยังได้รับ "object ไม่มีคำจำกัดความสำหรับ Foo"
กีฬา

@ กีฬาฉันด้วย ... คุณพบวิธีแก้ปัญหาหรือไม่? (ข้างToExpandoหนึ่ง)
Alex

2
ตอนนี้ในปี 2018 โดยใช้มุมมอง ASP.NET Core 2.1 และ Razor ฉันพบว่าข้อผิดพลาดในคำถามเดิมยังคงกัดฉันอยู่ ดังนั้นฉันไม่รู้ว่าสิ่งที่พูดถึงเกี่ยวกับ MVC 3 ในการแก้ไขนี้เป็นข้อมูลเกี่ยวกับอะไรเนื่องจากมันยังดูเหมือนเสียอยู่
Andrew Arnott

41

บน. NET 4.0 ชนิด Anonymous สามารถแปลงเป็น ExpandoObjects ได้อย่างง่ายดายดังนั้นปัญหาทั้งหมดจะได้รับการแก้ไขด้วยค่าโสหุ้ยของการแปลงเอง ตรวจสอบที่นี่


ยินดี. บางทีนี่อาจเป็นการเตะ M $ เพื่อให้ประเภทนิรนามใช้งานได้มากขึ้น
Adaptabi

สิ่งนี้ใช้ได้กับบางส่วนหรือไม่ ฉันได้รับข้อผิดพลาดว่า Partials ไม่สามารถส่งแบบไดนามิกได้ ...
John Bubriski

1
partials อะไร? คุณสามารถให้ตัวอย่างได้หรือไม่?
Adaptabi

27

สิ่งนี้ไม่เกี่ยวข้องกับประเภทนิรนามที่มีคุณสมบัติภายใน

เป็นไปได้อย่างสมบูรณ์แบบที่จะส่งผ่านประเภทที่ไม่ระบุตัวตนจากมุมมองไปยังมุมมองบางส่วน

ฉันพบปัญหาเดียวกันในวันนี้และไม่มีอะไรเกี่ยวข้องกับปัญหาในการส่งประเภทที่ไม่ระบุตัวตนและinternalคุณสมบัติโดยธรรมชาติ

ด้วยเหตุนี้ในส่วนที่เกี่ยวข้องกับคำถาม OP คำตอบของ @Lucas จึงไม่เกี่ยวข้อง - แม้ว่าวิธีแก้ปัญหาจะใช้ได้ผลก็ตาม

ในคำถาม OPs ประเภทที่ไม่ระบุตัวตนกำลังถูกส่งจากมุมมองในแอสเซมบลี X ไปยังบางส่วนในแอสเซมบลี Xดังนั้นปัญหาที่ David Ebbo ระบุถึงคุณสมบัติที่อยู่ภายในสำหรับประเภทที่ไม่ระบุตัวตนจึงไม่เป็นผล ประเภทเรียบเรียงสำหรับมุมมองที่บางส่วนและชนิดที่ไม่ระบุชื่อที่มีอยู่ทั้งหมดในการชุมนุมเดียวกัน

แล้วอะไรเป็นสาเหตุของความล้มเหลวอย่างกะทันหันในการส่งผ่านประเภทนิรนามจากมุมมองไปยังบางส่วน?

อย่างน้อยก็ในของฉันสถานการณ์ผมค้นพบว่ามันเป็นเพราะมีอีกมุมมองหนึ่งในโฟลเดอร์เดียวกันที่ระบุชนิดของรูปแบบที่ไม่สามารถแก้ไขได้ มุมมองจะถูกคอมไพล์ที่รันไทม์ดังนั้นมันจึงสมเหตุสมผลที่ความล้มเหลวในรันไทม์ในการคอมไพล์วิวก็หมายถึงความล้มเหลวในการคอมไพล์ประเภทไดนามิกและบางส่วนก็จะได้รับobjectไฟล์. ยังไม่ชัดเจนในทันทีว่าเกิดอะไรขึ้น แต่ในตัวอย่างเฉพาะของ OPs (และของฉัน) นี่เป็นสาเหตุของปัญหามากกว่า

เป็นที่น่าสนใจที่จะทราบว่าหากประเภทโมเดลถูกต้อง แต่ส่วนอื่นของมุมมองไม่คอมไพล์ประเภทที่ไม่ระบุตัวตนจะไม่ได้รับผลกระทบในลักษณะเดียวกัน สิ่งนี้ต้องลงไปถึงวิธีที่ Razor แบ่งการคอมไพล์แบบไดนามิกของส่วนคอมโพเนนต์ของมุมมอง

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

เพื่อให้แน่ใจว่าคุณจะไม่ถูกจับโดยสิ่งนี้อีกคุณสามารถเปิดใช้งานการรวบรวมเวลาคอมไพล์ของมุมมอง Razor ของคุณโดยเพิ่มสิ่งนี้ลงในcsprojไฟล์ของคุณ:

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

2
สิ่งนี้ช่วยแก้ปัญหาของฉันได้ - การใช้ "@model dynamic" ในตอนแรกดูเหมือนจะเป็นการแก้ไขที่ถูกต้อง แต่อันที่จริงกำลังพาฉันไปผิดทาง
crimbo

ฉันทำความสะอาดโซลูชันสร้างใหม่และข้อผิดพลาดหายไป .. 121 คะแนนโหวตผิด
maxbeaudoin

ฉันได้อัปเดตคำตอบเพื่อแสดงถึงการสนับสนุนของ MVC สำหรับโมเดลมุมมองแบบไดนามิกตั้งแต่ MVC 3
Lucas

การเปิดใช้งานการรวบรวมมุมมองเป็นครั้งคราวจะมีประโยชน์สำหรับฐานรหัสขนาดใหญ่เสมอ เปิดเผยปัญหาการพิมพ์ผิดข้อผิดพลาดทุกประเภทด้วย T4MVC ด้วยการพิมพ์ที่ชัดเจนเป็นต้น
Denis The Menace

โอ้ใช่: ฉันเพิ่งสังเกตว่าเรากำลังพูดถึงการส่งผ่านจากมุมมองไปยังบางส่วนที่นี่ ไม่ใช่จากคอนโทรลเลอร์ไปยังมุมมองซึ่งเป็นปัญหาของฉัน
mwardm

9

เพิ่มคลาสต่อไปนี้ที่ใดก็ได้ในโซลูชันของคุณ (ใช้เนมสเปซระบบเพื่อให้พร้อมใช้งานโดยไม่ต้องเพิ่มการอ้างอิงใด ๆ ) -

    namespace System
    {
        public static class ExpandoHelper
        {
            public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

        }
    }

เมื่อคุณส่งโมเดลไปยังมุมมองให้แปลงเป็น Expando:

    return View(new {x=4, y=6}.ToExpando());

1
ดูเหมือนจะเป็นค่าใช้จ่ายที่ไม่จำเป็นสำหรับฉันในการสร้างวัตถุแบบไดนามิกก่อนแล้วจึงสร้าง ExpandoObject ... เพียงแค่สร้าง ExpandoObject แทน ..
Baz1nga

@ Baz1nga คุณทำไม่ได้ ... new Expando () {prop = value, ... } ซึ่งทำให้มีปัญหา ฉันใช้ JObject ของ Json.Net สำหรับการใช้งานที่คล้ายกัน
Tracker1

3
รู้สึกผิดที่มี HtmlHelper อยู่ในนั้น ... ExpandoObject ToExpando แบบคงที่สาธารณะ (อ็อบเจ็กต์นี้ o) {IDictionary <string, object> expando = new ExpandoObject (); foreach (var propertyInfo ใน o.GetType (). GetProperties ()) {expando.Add (ใหม่ KeyValuePair <string, object> (propertyInfo.Name, propertyInfo.GetValue (o, index: null))); } return (ExpandoObject) expando; }
erlando

6

แทนที่จะใช้dynamicประเภท Model ภายในมุมมองบางส่วน

คุณสามารถเรียกใช้แอตทริบิวต์ออบเจ็กต์ที่ไม่ระบุชื่อโดยใช้@ViewData.Eval("foo")แทน@Model.foo.

จากนั้นคุณสามารถลบออก@Model dynamicจากมุมมองได้

เมื่อเร็ว ๆ นี้ฉันพบปัญหานี้เมื่อส่งผ่านคุณลักษณะบางอย่างระหว่างมุมมองสำหรับการผสานรวมความคิดเห็นทางสังคมของ Facebook รหัสตัวอย่าง:

Html.RenderPartial(@"Layouts/Partials/_Comments", new {currentUrl = Model.CurrentPage.GetAbsoluteUrl(), commentCount = 5 });

จากนั้นในมุมมองของฉันฉันมี div นี้:

<div class="fb-comments" data-href="@ViewData.Eval("currentUrl")" data-numposts="@ViewData.Eval("commentCount")" data-width="100%"></div>

0

ฉันไม่แน่ใจว่าคุณได้รับข้อผิดพลาดนี้เนื่องจากคุณไม่ได้ใช้วิธีแก้ปัญหา ฉันได้รับข้อผิดพลาดเดียวกันในมุมมองบางส่วน วิธีแก้ปัญหาก็แค่ทำความสะอาดบิวด์และสร้างใหม่ หากไวยากรณ์ถูกต้องโค้ดควรใช้งานได้ แต่เอ็นจินมีดโกนอาจอัปเดตโค้ดไม่ถูกต้อง


0

ฉันแก้ไขปัญหานี้โดยใช้พจนานุกรม

 @Html.Partial("_Partial", new Dictionary<string, string> { { "Key1", "Val1" }, { "Key2", "Val2" }, { "Key3", "Val3" } });

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