không thể tuần tự hóa phản hồi trong API Web


86

Tôi đang làm việc trên API web ASP.NET MVC, tôi gặp lỗi này:

Loại 'ObjectContent`1' không thể tuần tự hóa phần thân phản hồi cho loại nội dung 'application / xml; charset = utf-8 '.

Bộ điều khiển của tôi là:

public Employee GetEmployees()
{
    Employee employees = db.Employees.First();
    return employees;
}

tại sao tôi nhận được lỗi này?


6
Ngoại lệ bạn đang thấy là ngoại lệ chung, có thể do bất kỳ yếu tố nào gây ra. Kiểm tra thuộc InnerExceptiontính của ngoại lệ tuần tự hóa để tìm ra nguyên nhân chính xác khiến quá trình tuần tự hóa không thành công.
Tên hiển thị

Bạn có thể chia sẻ mã cho loại Nhân viên của bạn không? Nó có thể là do các loại nhân viên không phải là serializable ...
Maggie Ying


Câu trả lời:


121

Đối với tôi, đây là một vấn đề với việc tham chiếu vòng tròn.

Câu trả lời được chấp nhận không hoạt động với tôi vì nó chỉ thay đổi hành vi của trình định dạng JSON, nhưng tôi nhận được XML khi tôi gọi dịch vụ từ trình duyệt.

Để khắc phục điều này, tôi đã tắt XML và chỉ buộc trả lại JSON.

Trong tệp Global.asax, hãy đặt các dòng sau ở đầu phương thức Application_Start của bạn:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Bây giờ chỉ các kết quả JSON sẽ được trả về. Nếu bạn cần kết quả XML, bạn sẽ cần tìm một giải pháp khác.


đã làm việc cho tôi. nhưng vấn đề là tôi đang sử dụng POSTMAN. đó là một tiện ích mở rộng của chrome. khi tôi đăng dữ liệu với POSTMAN, nó hoạt động tốt. nhưng khi tôi sử dụng restsharp nó cho tôi lỗi này. nào giải pháp của bạn cố định vấn đề của tôi
ArgeKumandan

Câu trả lời này không cung cấp giải pháp để sử dụng xml và đó là những gì anh ta yêu cầu.
honestduane

Hoạt động cho tôi khi tôi chuyển sang json từ xml.
Sike

Trên thực tế, câu trả lời này đi vào gốc rễ của vấn đề. Lỗi đầu tiên tôi nhận được là lỗi tham chiếu vòng tròn (cố gắng trả lại JSON từ bộ điều khiển MVC). Khi tôi chuyển sang bộ điều khiển được kế thừa API, thay vào đó tôi bắt đầu gặp lỗi này. Khi tôi thêm mã ở trên vào Global.asax, lỗi đã biến mất.
Matthew Pitts

43

trong tệp global.asax của bạn, trong phương thức Application_start (), hãy thêm dòng này:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Tôi hy vọng rằng sẽ giúp bạn!


3
Application_start là gì và có thể tìm thấy nó ở đâu? Và chính xác thì dòng này nên được đặt ở đâu?
Ciaran Gallagher

4
Xin lỗi nhưng ý nghĩa của câu nói này là gì?
Blaise

5
Dòng được thêm vào Global.asax's Application_Start, nhưng không có thay đổi.
pho mát

8
Điều này vẫn không làm việc cho tôi. Tuy nhiên, tôi đã thêm một dòng khác sau dòng trong câu trả lời này và nó hoạt động: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); Tôi đã tạo ra một câu trả lời đầy đủ hơn dưới đây
Zane

2
Không nên chấp nhận câu trả lời này vì nó thực sự loại bỏ XmlSerializer thay vì giải quyết vấn đề tham chiếu vòng tròn với XmlSerializer.
Tin

29

Tôi có cùng một vấn đề. Và tôi đã giải quyết được nó. Tôi đặt hàm tạo mặc định cho lớp DTO.

Ví dụ:

public class User
{
    public User()
    {
    }
}

Hy vọng nó làm việc với bạn!


Cảm ơn về đề xuất, điều này đã giúp tôi với phản hồi xml, nhưng có ai biết tại sao nó cần một hàm tạo mặc định không? Chúng tôi có các dữ liệu đã ...
Ilya Chernomordik

Tôi nghĩ rằng khi một đối tượng được tuần tự hóa từ phản hồi, đầu tiên hàm tạo được gọi để tạo thể hiện của đối tượng, sau đó, phương thức set được sử dụng để thiết lập dữ liệu cho đối tượng. Đó là suy đoán của tôi.
taynguyen

Đây thực sự nên là câu trả lời được chọn vì nó không đưa ra bất kỳ giả định nào về các loại trả lại bạn cần. Điều này sẽ hoạt động cho cả XML và JSON. Cảm ơn vì đã đăng bài này.
Allen Underwood

22

Đặt cái này trong hàm tạo. Hy vọng điều này giải quyết được vấn đề:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

Giải pháp tuyệt vời. Tôi cần đặt nó vào hàm tạo và nó đã hoạt động.
InsParbo

Điều này làm việc cho tôi kết hợp với cài đặt GlobalConfiguration. Nhưng tại sao điều này lại hoạt động? Bất kỳ lời giải thích nào về cách điều này khắc phục sự cố? Và vấn đề thực sự là gì?
Ciaran Gallagher

Để hiểu proxy thực thể là gì: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Để hiểu ProxyCreationEnabled là gì: stackoverflow.com/questions/7111109/…
Sadjad Khazaie

16

Tôi tìm thấy hai giải pháp cho điều này. Đầu tiên và dễ thực hiện nhất là thay đổi bất kỳ IEnumerables, ICollections thành một loại Danh sách. WebAPI có thể tuần tự hóa các đối tượng này, tuy nhiên nó không thể tuần tự hóa các kiểu giao diện.

public class Store
{

  [StringLength(5)]
    public string Zip5 { get; set; }

    public virtual List<StoreReport> StoreReports { get; set; }  //use a list here
 }

Tùy chọn khác là không sử dụng trình tuần tự JSON gốc và chạy ghi đè này trong phương thức Đăng ký của Cấu hình WebApi:

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
        config.Formatters.Remove(config.Formatters.XmlFormatter);

1
Trong khi thay đổi vào danh sách làm việc cho tôi thêm một constructor parameterless cũng làm việc cho tôi và tôi có thể tiếp tục trở lại IEnumerable <Widget>
Mike Cheel

8

Giải pháp rất đơn giản.

Sau khi truy vấn LINQ thêm .ToList () (hoặc ToDictionary nếu cần).

Nó sẽ tải nhanh hơn tải dữ liệu chậm


1
Thay đổi kiểu trả về hành động thành IENumerablevà thêm .TiList()vào kiểu trả về đã phù hợp với tôi.
Ricardo Souza

5

** lỗi này xảy ra khi gọi từ yêu cầu web api / wcf / ... từ phía máy khách, nhưng do tác dụng phụ, bạn sẽ cần phải bao gồm các quan hệ tùy thuộc bằng từ khóa include. **

public CustomerPortalContext()
            : base("Name=CustomerPortalContext")
        {
            base.Configuration.ProxyCreationEnabled = false;
        }

4

Nếu bạn đang làm việc với EF, ngoài việc thêm mã bên dưới vào Global.asax

            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);          

Đừng quên nhập

using System.Data.Entity;

Sau đó, bạn có thể trả lại các Mô hình EF của riêng mình



3

Nếu bạn sử dụng api web với Entity Framework, giải pháp có thể không thành công để tuần tự hóa phản hồi trong API Web với Json

Về cơ bản, bạn cần tạo một mô hình tương ứng với từng mô hình EF, điều này loại bỏ sự phụ thuộc giữa các lớp và cho phép tuần tự hóa dễ dàng.

Mã: (lấy từ liên kết tham khảo)

Tạo UserModel

public class UserModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Thay đổi phương thức GetAll () của tôi

public IEnumerable<UserModel> GetAll()
{
    using (Database db = new Database ())
    {
        List<UserModel> listOfUsers = new List<UserModel>();
        UserModel userModel = new UserModel();
        foreach(var user in db.Users)
        {
           userModel.FirstName = user.FirstName;
           userModel.LastName = user.LastName;
           listOfUsers.Add(userModel);
        }
        IEnumerable<UserModel> users = listOfUsers;

        return users;
    }
}

2

Thực thể mặc định 6 sử dụng XML để apis, trong dự án của bạn, hãy tìm tệp "Global.asax" Tệp và thêm dòng này:

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

Dòng này loại bỏ Định dạng XML.


Xin chào, Web API serialize các phản ứng trong XML và JSON, nếu bạn thêm tiêu đề Content-Type: application / json, phản ứng là trong JSON, bạn cần xác định tiêu đề này, trong trình duyệt luôn bạn có thể xem nó như là định dạng XML
Roberth Solís

1

nhưng nếu bạn tìm thấy vấn đề này với các thực thể / lớp khác, bạn phải tạo DTO mới cho mỗi lớp và nếu bạn có nhiều trong số chúng, bạn có thể tìm thấy vấn đề, tôi cũng nghĩ rằng tạo DTO chỉ để giải quyết vấn đề này không phải là cách tốt nhất ...

Bạn đã thử cái này chưa?

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
Newtonsoft.Json.PreserveReferencesHandling.All;

Trân trọng


1

hmmm, Sau đây có thể hữu ích.

Tôi cũng nhận được một ngoại lệ tương tự và trong trường hợp của tôi, tôi đã chuyển thực thể poco thực tế được tạo cho mã thực thể trước. Vì nó chứa mối quan hệ với các thực thể khác, tôi chỉ tạo thực thể viewmapper / dto trên đầu nó để trả về.

Nó hoạt động tốt bây giờ.

Thực thể Poco:

public class Tag
{
public int Id{get;set;}
public string Title{get;set;}
public IList<Location> Locations{get;set;}
}

ViewMapper / Dto

public class TagResultsViewMapper
{
public int Id{get;set;}
public string Title{get;set;}
//just remove the following relationship 
//public IList<Location> Locations{get;set;}
}

0

Câu hỏi của bạn khá giống với câu hỏi của tôi. Bạn không được trực tiếp trả lại dữ liệu từ cơ sở dữ liệu. Đối với điều này, bạn phải tạo Mô hình và liên kết dữ liệu bạn muốn hiển thị.

Trong ví dụ của tôi, Có dữ liệu về Người dùng mà Json không thể tuần tự hóa, tôi đã tạo một userModel và trong API của tôi, tôi trả về userModel thay vì Người dùng từ cơ sở dữ liệu.

Logic chuyển đổi hoặc liên kết dữ liệu giữa Người dùng và Mô hình người dùng phải nằm trong API.

Không thể tuần tự hóa phản hồi trong API Web với Json


0

Đây là lỗi cụ thể mà tôi gặp lại từ lệnh gọi API Web odata của mình:

The 'ObjectContent`1' type failed to serialize the response 
body for content type 'application/json; odata.metadata=minimal'.

Cuối cùng tôi đã phát hiện ra rằng lớp dbContext của tôi có một tên bảng được định dạng kém được gán trong onModelCreating .. vì vậy SqlClient đang chết dần khi tìm kiếm một bảng không tồn tại trong db của tôi !!

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.