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.