Mô hình động MVC Razor, 'đối tượng' không chứa định nghĩa cho 'Tên tài sản'


106

Sử dụng MVC 3 với công cụ xem Razor. Tôi có Chế độ xem này:

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

Nó được gọi từ một chế độ xem khác bằng cách sử dụng mã này:

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

Trong cả hai Chế độ xem, khi tôi gỡ lỗi chúng và xem Mô hình, nó dường như chứa đối tượng chính xác. Khi tôi thực thi mã, tôi gặp lỗi trên dòng "var products =" cho biết:

'object' không chứa định nghĩa cho 'Sản phẩm'

Bất cứ ai có thể giải thích cho tôi tại sao tôi gặp lỗi đó? Một lần nữa, khi tôi xem đối tượng Model ở chế độ gỡ lỗi, nó có vẻ ổn (có 2 thuộc tính: Sản phẩm và Ngưỡng)


Câu trả lời:


150

Bạn có đang chuyển một phiên bản của lớp ẩn danh làm mô hình chế độ xem không? Tôi vừa thử cái này (mô hình chế độ xem động trong CSHTML) và gặp lỗi tương tự như của bạn khi sử dụng lớp ẩn danh, nhưng nó hoạt động tốt nếu tôi tạo một lớp được đặt tên. Tôi đã tìm kiếm nhưng không thấy tài liệu này ở đâu.

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

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

CHỈNH SỬA # 1:

Theo David Ebbo , bạn không thể chuyển một kiểu ẩn danh vào chế độ xem được nhập động vì các kiểu ẩn danh được biên dịch dưới dạng internal. Vì dạng xem CSHTML được biên dịch thành một hội đồng riêng biệt, nó không thể truy cập các thuộc tính của kiểu ẩn danh.

CHỈNH SỬA # 2:

David Ebbo đã chỉnh sửa bài đăng của mình với sự làm rõ này:

Lưu ý (22/12/2011): hiện tại MVC 3 đã hỗ trợ trực tiếp cho động, kỹ thuật dưới đây không còn cần thiết nữa. Bài đăng này trên thực tế là nguyên nhân dẫn đến việc tích hợp tính năng này vào MVC!


1
Bản chỉnh sửa là rất tốt để biết. Tôi vừa gặp vấn đề tương tự và không hiểu WTF ở đó. Cảm ơn vì lời giải thích.
Yanick Rochon

18
CHỈNH SỬA # 2 gợi ý rằng bây giờ (MVC> 3) có thể thực hiện dòng đến được đánh dấu bằng "lỗi" không? return View(new { Foo = 1, Bar = "test" });? Bởi vì tôi đang sử dụng MVC 4 và vẫn nhận được "đối tượng không chứa định nghĩa cho Foo"
sports

@sports tôi cũng vậy ... bạn đã tìm ra cách giải quyết chưa? (bên cạnh ToExpandomột)
Alex

2
Vì vậy, bây giờ vào năm 2018 bằng cách sử dụng ASP.NET Core 2.1 và chế độ xem Razor, tôi thấy lỗi trong câu hỏi ban đầu vẫn đang cắn tôi. Vì vậy, tôi không biết cuộc nói chuyện về việc sửa chữa MVC 3 này là về điều gì, vì nó vẫn có vẻ bị hỏng.
Andrew Arnott

41

Trên .NET 4.0, các loại Anonymous có thể dễ dàng được chuyển đổi thành ExpandoObjects và do đó tất cả các vấn đề đã được khắc phục với chi phí chuyển đổi chính nó. Kiểm tra tại đây


Không có gì. Có lẽ điều này thúc đẩy M $ để làm cho các loại ẩn danh dễ sử dụng hơn
Adaptabi

Tuy nhiên, điều này có áp dụng cho các Bên không? Tôi gặp lỗi không thể gửi động các Bộ phận ...
John Bubriski

1
Tiệc tùng gì? bạn có thể cung cấp một ví dụ?
Adaptabi

27

Điều này không liên quan gì đến các loại ẩn danh có thuộc tính nội bộ

Đó là hoàn toàn có thể vượt qua các kiểu nặc danh từ một cái nhìn đến một cái nhìn cục bộ

Tôi đã gặp phải vấn đề tương tự ngày hôm nay và không có gì (trực tiếp) liên quan đến vấn đề chuyển các kiểu ẩn danh và các internalthuộc tính vốn có của chúng .

Do đó, liên quan đến câu hỏi OP, câu trả lời của @Lucas là không liên quan - mặc dù giải pháp thay thế sẽ hoạt động .

Trong câu hỏi OPs, một kiểu ẩn danh đang được chuyển từ một khung nhìn trong hợp ngữ X sang một phần trong hợp ngữ X , do đó, vấn đề mà David Ebbo đã nêu ra về các thuộc tính nội bộ cho các kiểu ẩn danh không có hậu quả; các kiểu được biên dịch cho dạng xem, kiểu từng phần và kiểu ẩn danh đều được chứa trong cùng một assembly .

Vậy điều gì đang gây ra lỗi đột ngột không thể chuyển một loại ẩn danh từ một chế độ xem sang một phần?

Ít nhất là trong tình huống của tôi , tôi phát hiện ra rằng đó là do có một chế độ xem khác trong THƯ MỤC CÙNG chỉ định một loại mô hình không thể giải quyết được . Các khung nhìn được biên dịch trong thời gian chạy, và do đó, việc biên dịch các khung nhìn không thành công trong thời gian chạy cũng có nghĩa là không biên dịch được các kiểu động và một phần sẽ chỉ nhận được một object. Không rõ ràng ngay lập tức điều gì đang xảy ra, nhưng trong ví dụ cụ thể của OPs (và của tôi), đây nhiều khả năng là nguyên nhân của vấn đề.

Điều thú vị là nếu kiểu mô hình là đúng nhưng một phần khác của khung nhìn không biên dịch thì các kiểu ẩn danh không bị ảnh hưởng theo cách tương tự. Đây phải là cách Razor phá vỡ quá trình biên dịch động của các phần thành phần của khung nhìn.

Sau khi bạn sửa chế độ xem vi phạm, hãy xây dựng lại toàn bộ giải pháp hoặc dọn dẹp và xây dựng lại dự án trước khi kiểm tra xem nó đã được sửa chưa.

Để đảm bảo bạn không bị phát hiện bởi điều này một lần nữa, bạn có thể cho phép biên dịch thời gian biên dịch các chế độ xem Razor của bạn bằng cách thêm nó vào csprojtệp của bạn :

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

2
Điều này đã khắc phục sự cố của tôi - sử dụng "@model dynamic" ban đầu có vẻ như là cách khắc phục đúng, nhưng trên thực tế đã đưa tôi đi sai đường.
crimbo

Tôi đã làm sạch dung dịch, xây dựng lại nó và lỗi đã biến mất .. 121 phiếu up đặt sai vị trí.
maxbeaudoin

Tôi đã cập nhật câu trả lời của mình để phản ánh sự hỗ trợ của MVC cho các mô hình chế độ xem động kể từ MVC 3.
Lucas

Việc kích hoạt biên dịch lượt xem theo thời gian luôn hữu ích cho cơ sở mã khổng lồ. Tiết lộ tất cả các loại vấn đề, lỗi chính tả, lỗi với T4MVC nhờ mạnh gõ nó giới thiệu, vv
Denis Các Menace

Ồ, đúng rồi: Tôi vừa nhận thấy rằng chúng ta đang nói về việc chuyển từ một góc nhìn sang một phần ở đây. Không phải từ bộ điều khiển sang chế độ xem, đó là vấn đề của tôi.
mwardm

9

Thêm lớp sau vào bất kỳ đâu trong giải pháp của bạn (sử dụng không gian tên Hệ thống, để nó sẵn sàng sử dụng mà không cần phải thêm bất kỳ tham chiếu nào) -

    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;
            }

        }
    }

Khi bạn gửi mô hình đến dạng xem, hãy chuyển đổi nó thành Expando:

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

1
có vẻ như một overhead unnecssary với tôi để tạo ra một đối tượng năng động đầu tiên và sau đó tạo ra một ExpandoObject ... Chỉ cần tạo các ExpandoObject thay vì ..
Baz1nga

@ Baz1nga Bạn không thể làm ... new Expando () {prop = value, ...}, điều này khiến nó có vấn đề. Tôi đang sử dụng Json.Net's JObject để sử dụng tương tự.
Tracker1

3
Cảm thấy sai khi có HtmlHelper trong đó ... public static ExpandoObject ToExpando (đối tượng này o) {IDictionary <string, object> expando = new ExpandoObject (); foreach (var propertyInfo in o.GetType (). GetProperties ()) {expando.Add (new KeyValuePair <string, object> (propertyInfo.Name, propertyInfo.GetValue (o, index: null))); } return (ExpandoObject) expando; }
erlando

6

Thay vì sử dụng dynamickiểu Model trong chế độ xem từng phần.

Bạn có thể gọi các thuộc tính đối tượng ẩn danh bằng cách sử dụng @ViewData.Eval("foo")thay vì @Model.foo.

Sau đó, bạn có thể xóa @Model dynamickhỏi chế độ xem.

Tôi đã gặp vấn đề này gần đây khi chuyển một số thuộc tính giữa các chế độ xem cho Tích hợp bình luận xã hội Facebook. Mã ví dụ:

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

Sau đó, theo quan điểm của tôi, tôi chỉ có div này:

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

0

Tôi không chắc rằng bạn đang gặp lỗi này vì bạn không triển khai công việc xung quanh. tôi gặp lỗi tương tự khi xem một phần. giải pháp chỉ là dọn dẹp tòa nhà và xây dựng lại nó. nếu cú ​​pháp đúng, mã sẽ hoạt động, nhưng công cụ dao cạo có thể không cập nhật các thay đổi mã đúng cách.


0

Tôi đã giải quyết vấn đề này bằng cách sử dụng Từ điển.

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

-6

Để sử dụng dynamicloại, bạn cần tham khảo Microsoft.CSharpassembly

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.