Web API에서 응답을 직렬화하지 못했습니다.


86

ASP.NET MVC 웹 API에서 작업 중이 었는데이 오류가 발생했습니다.

'ObjectContent`1'유형이 'application / xml'컨텐츠 유형에 대한 응답 본문을 직렬화하지 못했습니다. charset = utf-8 '입니다.

내 컨트롤러는 다음과 같습니다.

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

이 오류가 발생하는 이유는 무엇입니까?


6
표시되는 예외는 일반적인 예외이며 여러 요인으로 인해 발생할 수 있습니다. InnerException직렬화 예외 의 특성을 확인하여 정확히 직렬화 실패 원인을 찾으십시오.
— 표시 이름

직원 유형에 대한 코드를 공유 할 수 있습니까? 유형의 직원이 ... 직렬화 가능하지 않기 때문에 그것은있을 수 있습니다
— 매기 잉


답변:


121

나에게 이것은 순환 참조의 문제였습니다.

받아 들여진 대답은 JSON 포맷터의 동작 만 변경하기 때문에 저에게 효과가 없었지만 브라우저에서 서비스를 호출 할 때 XML을 얻었습니다.

이 문제를 해결하기 위해 XML을 끄고 JSON 만 반환하도록했습니다.

Global.asax 파일에서 Application_Start 메서드 맨 위에 다음 줄을 추가합니다.

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

이제 JSON 결과 만 반환됩니다. XML 결과가 필요한 경우 다른 솔루션을 찾아야합니다.


나를 위해 일했지만 POSTMAN을 사용하고 있습니다. 크롬 확장입니다. POSTMAN으로 데이터를 게시하면 제대로 작동합니다. 하지만 restsharp를 사용하면이 오류가 발생합니다. 어쨌든 귀하의 솔루션이 내 문제를 해결했습니다
— ArgeKumandan 2015 년

이 답변은 xml을 사용하는 솔루션을 제공하지 않으며 그가 요청한 것입니다.
— honestduane

xml에서 json으로 전환하면서 나를 위해 작동합니다.
— Sike12

실제로이 답변은 문제의 근원에 도달합니다. 내가받은 첫 번째 오류는 순환 참조 오류 (MVC 컨트롤러에서 JSON 반환 시도)였습니다. API 상속 컨트롤러로 전환했을 때 대신이 오류가 발생하기 시작했습니다. 위의 코드를 Global.asax에 추가하면 오류가 사라졌습니다.
— 매튜 피츠

43

global.asax 파일의 Application_start () 메서드에 다음 줄을 추가합니다.

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

도움이 되었기를 바랍니다.


3
application_start는 무엇이며 어디서 찾을 수 있습니까? 그리고이 선을 정확히 어디에 배치해야합니까?
— Ciaran Gallagher

4
죄송하지만이 문장의 의미는 무엇입니까?
— Blaise

5
추가 라인 Global.asax의 ' Application_Start하지만, 변화 없음.
— cheesus

8
이것은 여전히 ​​나를 위해 작동하지 않았습니다. 그러나 나는이 답변의 한 줄 뒤에 다른 줄을 추가했으며 작동했습니다. GlobalConfiguration.Configuration.Formatters.Remove (GlobalConfiguration.Configuration.Formatters.XmlFormatter); 나는 아래에 더 완전한 답변을 만들었습니다
— Zane

2
이 대답은 XmlSerializer를 사용하여 순환 참조 문제를 해결하는 대신 실제로 XmlSerializer를 제거하므로 받아 들여서는 안됩니다.
— Believe2014 2014 년

29

나는 같은 문제가 있습니다. 그리고 나는 그것을 해결했습니다. 기본 생성자를 DTO 클래스에 넣었습니다.

전의:

public class User
{
    public User()
    {
    }
}

당신과 함께 일하기를 바랍니다!


제안 해 주셔서 감사합니다. 이것은 xml 응답에 도움이되었지만 기본 생성자가 필요한 이유를 아는 사람이 있습니까? 우리는 ... 이미 데이터가
— 일리아 Chernomordik

객체가 응답에서 직렬화되면 먼저 생성자를 호출하여 객체의 인스턴스를 만든 다음 set 메서드를 사용하여 데이터를 객체 인스턴스로 설정한다고 생각합니다. 내 추측이다.
— taynguyen

필요한 반환 유형에 대해 어떤 가정도하지 않으므로 실제로 선택한 답변이어야합니다. 이것은 XML과 JSON 모두에서 작동합니다. 게시 해 주셔서 감사합니다.
— Allen Underwood

22

이것을 생성자에 넣으십시오. 이것이 문제를 해결하기를 바랍니다.

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

탁월한 솔루션. 생성자에 넣어야하고 작동했습니다.
— InsParbo

이것은 GlobalConfiguration 설정과 함께 저에게 효과적이었습니다. 그러나 이것이 작동하는 이유는 무엇입니까? 이것이 문제를 해결하는 방법에 대한 설명이 있습니까? 그리고 실제로 문제는 무엇입니까?
— Ciaran Gallagher

엔티티 프록시가 무엇인지 이해하려면 : msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx ProxyCreationEnabled가 무엇인지 이해하려면 : stackoverflow.com/questions/7111109/…
— Sadjad Khazaie

16

이에 대한 두 가지 해결책을 찾았습니다. 구현하기 가장 쉬운 첫 번째 방법은 IEnumerables, ICollections를 List 유형으로 변경하는 것입니다. WebAPI는이 개체를 직렬화 할 수 있지만 인터페이스 유형을 직렬화 할 수는 없습니다.

public class Store
{

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

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

다른 옵션은 네이티브 JSON 직렬 변환기를 사용하지 않고 WebApi Config의 Register 메서드에서이 재정의를 실행하는 것입니다.

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

1
목록에 변화는 매개 변수가없는 생성자는 나를 위해 일한 내가는 IEnumerable <위젯> 돌아 계속할 수 추가 나를 위해 일 동안
— 마이크 Cheel

8

해결책은 간단합니다.

LINQ 쿼리 후에 .ToList () (또는 필요한 경우 ToDictionary)를 추가합니다.

데이터의 지연로드보다 빠른로드를 수행합니다.


1
작업 반환 유형을로 변경하고 반환에 IENumerable추가 .TiList()하면 저에게 효과적이었습니다.
— Ricardo Souza 2015

5

**이 버그는 클라이언트 측에서 web api / wcf / ... 요청에서 호출 할 때 발생하지만 부작용으로 include 키워드로 의존 관계를 포함해야합니다. **

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

4

EF로 작업하는 경우 Global.asax에 아래 코드를 추가하는 것 외에

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

가져 오는 것을 잊지 마세요

using System.Data.Entity;

그런 다음 자신의 EF 모델을 반환 할 수 있습니다.



3

Entity Framework에서 웹 API를 사용하는 경우 솔루션 이 Json을 사용하여 Web API에서 응답을 직렬화하지 못할 수 있습니다.

기본적으로 각 EF 모델에 해당하는 모델을 만들어야합니다. 이렇게하면 클래스 간의 종속성이 제거되고 쉽게 직렬화 할 수 있습니다.

코드 : (참조 된 링크에서 가져옴)

UserModel 생성

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

내 메서드 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;
    }
}

2

Default Entity 6은 ​​XML 을 사용 하여 프로젝트에서 "Global.asax"파일을 찾아 다음 줄을 추가합니다.

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

이 줄은 XML 포맷터를 제거합니다.


안녕하세요, Web API는 응답을 XML과 JSON으로 직렬화합니다. Content-Type : application / json 헤더를 추가하면 응답이 JSON으로되어 있습니다.이 헤더를 정의해야합니다. 브라우저에서 항상 XML 형식으로 볼 수 있습니다
— Roberth Solís

1

하지만 다른 엔티티 / 클래스에서이 문제를 발견했다면 각 클래스에 대해 새로운 DTO를 생성해야하고, 그것들이 많으면 문제를 발견 할 수 있습니다. 또한 저는이 문제를 해결하기위한 DTO를 생성한다고 생각합니다. 최선의 방법은 아닙니다 ...

이거 해봤 어?

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

문안 인사


1

흠, 다음이 도움이 될 수 있습니다.

동일한 예외가 발생했으며 제 경우에는 엔티티 코드 용으로 생성 된 실제 poco 엔티티를 먼저 전달했습니다. 다른 엔터티와의 관계가 포함되어 있으므로 반환 할 viewmapper / dto 엔터티를 그 위에 만들었습니다.

이제 잘 작동합니다.

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

귀하의 질문은 저와 매우 유사합니다. 데이터베이스에서 직접 데이터를 반환해서는 안됩니다. 이를 위해 모델을 생성하고 표시하려는 데이터를 연결해야합니다.

내 예에서는 Json이 직렬화 할 수없는 User에 대한 데이터가 있고 userModel을 만들었고 API에서 데이터베이스에서 User 대신 userModel을 반환했습니다.

User와 UserModel 간의 데이터 변환 또는 연관 논리는 API에 있어야합니다.

Json을 사용하여 Web API에서 응답을 직렬화하지 못했습니다.


0

이것은 내 odata Web API 호출에서 돌아온 특정 오류였습니다.

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

나는 마침내 내 dbContext 클래스 에 onModelCreating에 할당되는 형식 이 잘못된 테이블 이름 이 있다는 것을 알아 냈다. 그래서 SqlClient는 내 db에 존재하지 않는 테이블을 찾고 죽어 가고 있었다 !

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.