gagal untuk membuat serial respon di Web API

86

Saya sedang mengerjakan API web ASP.NET MVC, saya mengalami kesalahan ini:

Jenis 'ObjectContent`1' gagal membuat serial tubuh respons untuk jenis konten 'application / xml; charset = utf-8 '.

Pengontrol saya adalah:

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

mengapa saya mendapatkan kesalahan ini?

Tamal kanti Dey
sumber
6
Pengecualian yang Anda lihat adalah pengecualian umum, yang dapat disebabkan oleh sejumlah faktor. Periksa InnerExceptionproperti pengecualian serialisasi untuk mencari tahu apa sebenarnya yang menyebabkan serialisasi gagal.
Nama Tampilan
Bisakah Anda membagikan kode untuk tipe Karyawan Anda? Mungkin karena tipe Employee is not serializable ...
Maggie Ying

Jawaban:

121

Bagi saya ini adalah masalah dengan referensi melingkar.

Jawaban yang diterima tidak berfungsi untuk saya karena hanya mengubah perilaku pemformat JSON, tetapi saya mendapatkan XML saat memanggil layanan dari browser.

Untuk memperbaikinya, saya mematikan XML dan memaksa hanya JSON yang dikembalikan.

Di file Global.asax, letakkan baris berikut di bagian atas metode Application_Start Anda:

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

Sekarang hanya hasil JSON yang akan dikembalikan. Jika Anda memerlukan hasil XML, Anda perlu mencari solusi lain.

Zane
sumber
bekerja untuk saya. tetapi masalahnya adalah saya menggunakan POSTMAN. itu ekstensi chrome. ketika saya memposting data dengan POSTMAN itu berfungsi dengan baik. tetapi ketika saya menggunakan restsharp itu memberi saya kesalahan ini. bagaimanapun solusi Anda memperbaiki masalah saya
ArgeKumandan
Jawaban ini tidak memberikan solusi untuk menggunakan xml, dan itulah yang dia minta.
honestduane
Bekerja untuk saya saat saya beralih ke json dari xml.
Sike12
Sebenarnya, jawaban ini sampai ke akar masalahnya. Kesalahan pertama yang saya terima adalah kesalahan referensi melingkar (mencoba mengembalikan JSON dari pengontrol MVC). Saat saya beralih ke pengontrol yang diwarisi API, saya mulai mendapatkan kesalahan ini. Ketika saya menambahkan kode di atas ke Global.asax kesalahannya hilang.
Matthew Pitts
43

di file global.asax Anda, dalam metode Application_start () tambahkan baris ini:

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

Saya harap itu membantu Anda!

Julito Avellaneda
sumber
3
Apa itu application_start dan di mana bisa ditemukan? Dan di mana tepatnya garis ini ditempatkan?
Ciaran Gallagher
4
Maaf tapi apa arti dari pernyataan ini?
Blaise
5
Baris ditambahkan ke Global.asax's Application_Start, tapi tidak ada perubahan.
cheesus
8
Ini masih tidak berhasil untuk saya. Namun saya menambahkan baris lain setelah yang ada di jawaban ini dan berhasil: GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); Saya telah membuat jawaban yang lebih lengkap di bawah
Zane
2
Jawaban ini tidak boleh diterima karena memang menghapus XmlSerializer daripada mengatasi masalah referensi melingkar dengan XmlSerializer.
Percaya2014
29

Saya punya masalah yang sama. Dan saya menyelesaikannya. Saya meletakkan konstruktor default ke kelas DTO.

Ex:

public class User
{
    public User()
    {
    }
}

Semoga berhasil dengan Anda!

taynguyen
sumber
Terima kasih atas sarannya, ini membantu saya dengan tanggapan xml, tetapi apakah ada yang tahu mengapa ia membutuhkan konstruktor default? Kami sudah memiliki datanya ...
Ilya Chernomordik
Saya pikir ketika suatu objek diserialkan dari respons, pertama konstruktor dipanggil untuk membuat instance objek, setelah itu, metode set digunakan untuk mengatur data ke instance objek. Itu tebakan saya.
taynguyen
Ini sebenarnya harus menjadi jawaban yang dipilih karena tidak membuat asumsi tentang jenis kembalian yang Anda butuhkan. Ini akan berfungsi untuk XML dan JSON. Terima kasih telah memposting ini.
Allen Underwood
22

Taruh ini di konstruktor. Semoga ini menyelesaikan masalah:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }
Sadjad Khazaie
sumber
Solusi luar biasa. Saya harus memasukkannya ke dalam konstruktor dan berhasil.
InsParbo
Ini bekerja untuk saya dalam kombinasi dengan pengaturan GlobalConfiguration. Tapi mengapa ini berhasil? Adakah penjelasan tentang bagaimana ini memperbaiki masalah? Dan apa masalahnya sebenarnya?
Ciaran Gallagher
Untuk memahami apa itu proxy entitas: msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx Untuk memahami apa itu ProxyCreationEnabled: stackoverflow.com/questions/7111109/…
Sadjad Khazaie
16

Saya menemukan dua solusi untuk ini. Yang pertama dan termudah untuk diterapkan adalah dengan mengubah IEnumerables, ICollections ke jenis List. WebAPI dapat membuat serial objek ini, namun tidak dapat membuat serial tipe antarmuka.

public class Store
{

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

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

Opsi lainnya adalah tidak menggunakan serializer JSON asli dan menjalankan penggantian ini dalam metode Register di WebApi Config:

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
        config.Formatters.Remove(config.Formatters.XmlFormatter);
Ray Suelzer
sumber
1
Sementara mengubah ke Daftar bekerja untuk saya menambahkan konstruktor tanpa parameter juga bekerja untuk saya dan saya dapat terus mengembalikan IEnumerable <Widget>
Mike Cheel
8

Solusinya sederhana.

Setelah kueri LINQ tambahkan .ToList () (atau ToDictionary jika perlu).

Ini akan melakukan eager loading dari pada lazy loading data

om471987
sumber
1
Mengubah jenis pengembalian tindakan ke IENumerabledan menambahkan .TiList()pengembalian berhasil untuk saya.
Ricardo Souza
5

** bug ini terjadi saat memanggil dari permintaan api web / wcf / ... dari sisi klien, tetapi sebagai efek sampingnya, Anda perlu menyertakan hubungan tergantung dengan memasukkan kata kunci. **

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

Jika Anda bekerja dengan EF, selain menambahkan kode di bawah ini di Global.asax

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

Jangan lupa untuk mengimpor

using System.Data.Entity;

Kemudian Anda dapat mengembalikan Model EF Anda sendiri

Lucas Roselli
sumber
3

Jika Anda menggunakan api web dengan Entity Framework, solusinya bisa gagal untuk membuat serial respon di Web API dengan Json

Pada dasarnya, Anda perlu membuat model yang sesuai dengan setiap model EF, ini menghilangkan ketergantungan antar kelas dan memungkinkan serialisasi yang mudah.

Kode: (diambil dari tautan referensi)

Buat UserModel

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

Ubah metode saya GetAll ()

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;
    }
}
Tung Nguyen
sumber
2

Entitas Default 6 menggunakan XML untuk apis, dalam proyek Anda, temukan file "Global.asax" File dan tambahkan baris ini:

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

Baris ini menghapus XML Formatter.

Roberth Solís
sumber
Halo, Web API membuat serial respon dalam XML dan JSON, jika Anda menambahkan header Content-Type: application / json, responnya ada di JSON, Anda perlu mendefinisikan header ini, di browser selalu Anda bisa melihatnya sebagai format XML
Roberth Solís
1

tetapi jika Anda menemukan masalah ini dengan entitas / kelas lain, Anda harus membuat DTO baru untuk setiap kelas, dan jika Anda memiliki banyak dari mereka, Anda dapat menemukan masalah, juga menurut saya membuat DTO hanya untuk menyelesaikan masalah ini bukanlah cara terbaik ...

Apakah kamu sudah mencobanya?

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

Salam

Julito Avellaneda
sumber
1

hmmm, Mengikuti semoga bisa membantu.

Saya mendapatkan pengecualian yang sama, dan dalam kasus saya, saya meneruskan entitas poco sebenarnya yang dibuat untuk kode entitas terlebih dahulu. Karena, ini berisi relasi dengan entitas lain, saya baru saja membuat entitas viewmapper / dto di atasnya untuk mengembalikannya.

Ini berfungsi dengan baik sekarang.

Entitas 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;}
}
aamir sajjad
sumber
0

Pertanyaan Anda sangat mirip dengan pertanyaan saya. Anda tidak boleh mengembalikan data dari database secara langsung. Untuk ini, Anda harus membuat Model dan mengaitkan data yang ingin Anda perlihatkan.

Dalam contoh saya, Ada data tentang User yang Json tidak bisa serialisasi, saya telah membuat userModel dan, di API saya, saya mengembalikan userModel sebagai gantinya User dari database.

Logika konversi atau data asosiasi antara User dan UserModel harus ada di API.

Gagal untuk membuat serial respon di Web API dengan Json

CampDev
sumber
0

Ini adalah kesalahan khusus yang saya dapatkan kembali dari panggilan API Web odata saya:

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

Saya akhirnya menemukan bahwa kelas dbContext saya memiliki nama tabel yang berformat buruk yang ditugaskan di onModelCreating .. jadi SqlClient sekarat mencari tabel yang tidak ada di db saya !!

bkwdesign.dll
sumber