2009-09-15 29 views
7

Tôi có một chế độ xem tùy chỉnh được tuần tự hóa bằng cách sử dụng JsonResult. ViewModel có một số thuộc tính phải được công khai, nhưng đồng thời các thuộc tính này sẽ không hiển thị trong kết quả Json kết quả.Làm cách nào để loại trừ một số thuộc tính công khai không được tuần tự hóa thành JsonResult?

Tôi đã thử sử dụng thuộc tính [NonSerialized], nhưng điều đó dường như không có bất kỳ ảnh hưởng nào.

Có cách nào đơn giản để thực hiện việc này không? Hoặc tôi sẽ phải mã loại kết quả của riêng tôi (trong trường hợp này tôi có thể sẽ không bận tâm)?

+0

Hầu hết câu trả lời đều sử dụng Thuộc tính hoặc bao hàm mọi thứ. Tôi chỉ muốn loại trừ một số thuộc tính công khai trong quá trình tuần tự hóa. Tôi đang tìm JSON.NET theo gợi ý của @Charlino nhưng did'nt tìm thấy con đường. Đây là trường hợp: Tôi có thuộc tính 'Lỗi' sẽ chỉ được đặt khi xảy ra lỗi. phía máy khách sẽ kiểm tra điều này trước tiên để hiển thị tin nhắn nếu không sẽ hiển thị phần còn lại của thuộc tính Mô hình. Khi không có lỗi, nó sẽ trả về '{...," Lỗi ": null}'! – CallMeLaNN

Trả lời

24

Bạn có thể đặt thuộc tính [ScriptIgnore] trên các thành viên không được đăng theo thứ tự. Xem ScriptIgnoreAttribute Class in MSDN để biết ví dụ.

+8

cho những người khác ngoài kia không gian tên đầy đủ của thuộc tính là [System.Web.Script.Serialization.ScriptIgnore] – EBarr

+0

Có vẻ như 'ScriptIgnore' khi sử dụng MVC' return Json() '---' JsonIgnore' nếu sử dụng 'Json.NET' – mmcrae

0

Không chính xác câu trả lời bạn đang tìm kiếm, nhưng bạn có thể lừa gạt Json() sử dụng đoạn mã sau và các lớp học vô danh:

MyModel model = ...; 
return Json(new MyModel {model.Prop1, model.Prop2}); 
+0

Tôi biết tôi có thể sử dụng các loại ẩn danh để thay thế. Nhưng điều đó khiến đơn vị kiểm tra kết quả khó hơn nhiều. Nó có nghĩa là tôi sẽ phải phân tích cú pháp kết quả tuần tự hóa hoặc sử dụng sự phản chiếu. –

+0

Kiểm tra đơn vị JsonResults là khó khăn để bắt đầu. Làm thế nào bạn làm điều này trước đây? Nó không giống như bạn có thể lấy mô hình cơ bản mà lái xe JsonResult. –

+1

Không có vấn đề gì cả. thuộc tính JsonResult.Data chứa đối tượng sẽ được tuần tự hóa. Vì tôi đang sử dụng một viewmodel tùy chỉnh thay vì một kiểu đối tượng ẩn danh, tôi có thể chỉ cần lấy đối tượng đó và kiểm tra các thuộc tính của nó. –

0

Bạn có thể tạo ra một lớp wrapper đó cho thấy nhiều chỉ những thuộc tính mà bạn muốn trong JsonResult. Trong ví dụ dưới đây, Cow có 2 thuộc tính - "Leg" và "Moo". Giả sử bạn muốn chỉ hiển thị "Chân" làm thuộc tính. Sau đó

Dim cw như CowWrapper = New CowWrapper (c)

sẽ trả về một lớp wrapper mà chỉ làm lộ ra "chân". Điều này cũng hữu ích cho những thứ như DataGridView nếu bạn chỉ muốn hiển thị một số tập con của các thuộc tính.

Công Class Bò

Công ReadOnly Leg tuệ() như String

get 

     return "leg" 

    end get 

cuối tài sản

Công ReadOnly Moo tuệ() như String

get 

     return "moo" 

    end get 

cuối tài sản

lớp cuối

Công Lớp CowWrapper

Private m_cow as Cow = Nothing 

Public Sub New(ByVal cow as Cow) 

    m_cow = cow 

end Sub 


    m_cow = cow 

Công ReadOnly Leg tuệ() như String

get 

     return m_cow.Leg() 

    end get 

cuối tài sản

cuối Lớp

+0

Điều này làm việc, nhưng ở mức giá phải sao chép khá một vài tài sản, vì vậy nó không thực sự những gì tôi đang tìm kiếm. –

+0

Với chi phí nào? Lập trình? Nó sẽ đơn giản để viết một tiện ích đơn giản để xây dựng các lớp này cho tệp lớp làm đầu vào hoặc để viết một lớp có thể xây dựng các thuộc tính động bằng cách sử dụng nội suy. Thời gian chạy? Chi phí của một tham chiếu thêm là không thể tin được. –

+0

Tôi đã không nhận ra bạn có nghĩa là xây dựng các loại như vậy tại thời gian chạy thông qua sự phản ánh. Điều đó tất nhiên sẽ bao gồm tất cả các loại chế độ xem tùy chỉnh của tôi mà không cần thêm bất kỳ mã nào. Một cách tiếp cận hợp lệ nhưng nó quá phức tạp so với việc sử dụng một công cụ làm sẵn (cụ thể là Json.Net) –

1

Mở rộng lớp JavaScriptConverter để không bao gồm quảng cáo rties với số NonSerializedAttribute. Sau đó, bạn có thể tạo một tùy chỉnh ActionResult sử dụng JavaScriptConverter để sắp xếp thứ tự đối tượng.

Điều này tạo ra một lớp học vững chắc và có thể kiểm tra mà không cần phải tạo lại các lớp trình bao bọc hoặc sử dụng các đối tượng ẩn danh.

+0

Đó là cách tiếp cận mà tôi nghĩ đến. Nó chắc chắn hoạt động, nhưng vì đây chỉ là tiết kiệm một vài byte của mỗi yêu cầu Json, tôi đã hy vọng có một cái gì đó đơn giản hơn. Cách tiếp cận tốt, nhưng chỉ đơn giản là quá nhiều công việc so với những lợi ích trong trường hợp của tôi. –

2

Hãy xem JSON.NET từ James Newton-King. Nó sẽ làm những gì bạn đang tìm kiếm.

+0

Hoàn hảo! Khi nó quay ra, James cũng đã viết một loại JsonResult phù hợp: http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net.aspx –

2

Chỉ cần tạo giao diện để trả lại thay vì một lớp.

public interface IMyViewModel { 
    string MyPublicProperty { get; set; } 
} 

Sau đó tạo một lớp kế thừa giao diện

public class MyViewModel : IMyViewModel { 
    public string MyPublicProperty { get; set; } 
    public string MyNotSoPublicProperty { get; set; } 
} 

Và trở lại giao diện, không phải là lớp học, trong Controller Action

public JsonResult MyJson(){ 
    IMyViewModel model = new MyViewModel(); 
    return Json(model); 
} 

Và kết quả JSON sẽ

{ 
    'MyPublicProperty': '' 
} 

Một trong những thách thức trong kịch bản phía máy khách là, nếu bạn đang thay đổi các lớp học của mình, bạn không biết liệu bạn có đang hủy hoại việc triển khai phía máy khách hay không. Nếu bạn sử dụng các loại giao diện trong JSON của mình, bạn hiểu rằng nếu bạn thay đổi giao diện, bạn đang làm một thứ có khả năng có thể giết chết việc triển khai phía máy khách. Và nó cũng giúp bạn tiết kiệm từ việc kiểm tra lại phía máy khách một cách vô ích nếu bạn đang thay đổi thứ gì đó KHÔNG ở dạng inteface (do đó không được sắp xếp theo thứ tự).

Ngoài ra, nhiều lần, Chế độ xem của bạn có thể có các bộ sưu tập lớn hoặc các loại phức tạp trong chúng mà bạn không nhất thiết muốn xuất ra máy khách. Việc này có thể mất nhiều thời gian để tuần tự hóa hoặc hiển thị thông tin đơn giản không thuộc về mã máy khách. Sử dụng giao diện sẽ làm cho nó minh bạch hơn để biết những gì đang được trong đầu ra. Ngoài ra, việc sử dụng các thuộc tính như [ScriptIgnore] trên một thuộc tính chỉ áp dụng cho một trường hợp cụ thể (JavaScript Serialization) buộc bạn phải đối mặt với cùng một vấn đề nếu sau đó bạn đang nối tiếp với XML chẳng hạn. Điều này sẽ không cần thiết phân phối viewmodels của bạn với tấn thuộc tính. Có bao nhiêu người trong số họ thực sự muốn ở đó? Sử dụng intefaces áp dụng bất cứ nơi nào và không có viewmodel cần phải được rải rác với các thuộc tính phụ.

+0

Cảm ơn câu trả lời của bạn. Nó không phải là một phương thức xấu, nhưng cũng có một cách tự động hơn để đảm bảo rằng các lớp phía máy khách của bạn vẫn được đồng bộ với phía máy chủ: Sử dụng Typescript cho mã phía máy khách và tạo các khung nhìn phía máy khách của bạn từ các đối tượng phía máy chủ trong quá trình biên dịch. Xem http://type.litesolutions.net/ để biết thêm chi tiết. –

+0

Cách tiếp cận này có hoạt động với một List đang được tuần tự hóa không? Tôi không thể làm cho nó hoạt động ... – tomasofen

Các vấn đề liên quan