2017-02-13 2 views
0

GET, POST 및 PUT간에 균등하게 분할 된 수십 개의 RESTful 메서드가있는 웹 API 프로젝트가 있습니다. 이 시스템은 Nuget의 Entity Framework 객체와 Newtonsoft의 JSON (버전 9.0.1)을 사용합니다.POST 및 PUT ReadAsAsync()가 null이지만 ReadAsStringAsync()가 채워진 이유는 무엇입니까? 일명 "청킹을 해제하려면 어떻게합니까?"

내가 최근에 한 일은 갑자기 모든 POST와 PUT을 손상 시켰습니다. 나는 POST/PUTting 인 [FromBody] 객체가 null로 도착한다는 것을 알게되었습니다.

그래서 내 "사용자 업데이트"방법은 ...과 같이

[HttpPut] 
    public IHttpActionResult Put([FromBody] User user) 

보이는 ...하지만 "사용자는"항상 null 도착한다. 마찬가지로 이렇게하면 ...

var obj = Request.Content.ReadAsAsync<object>().Result; 

... 그러면 obj가 null입니다. 나는이 작업을 수행 할 경우

는하지만 ...

var jsonString = Request.Content.ReadAsStringAsync().Result; 

는 ... 그때는 예상 JSON을 얻을. (그러나 내 아키텍처에서는 JSON을 원하지 않는다. 객체를 원한다.) 은 이미 요청을 읽었을 때 이해할 수있는 것으로 예상된다. 함유량. 내용 스트림은 되감기 가능하지 않으며 마지막 바이트로 설정됩니다. .ReadAsStringAsync() 및 .ReadAsByteArrayAsync()는 스트림을 복사하고 처리하는 것으로 가정합니다.

나는 이것을 HttpClient를 사용하는 WPF 응용 프로그램에서 호출합니다. 샘플 호출 ...

using (HttpClient http = API.GetHttpClient()) 
{ 
    string url = string.Format("{0}/User", thisApp.WebAPI_BaseUrl); 
    RILogManager.Default.SendString("url", url); 

    JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter() ; 
    formatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

    HttpResponseMessage response; 

    response = http.PutAsync<User>(url, user, formatter, "application/json").Result; 
    ... 

내 "API.GetHttpClient()"루틴은 다음과 같습니다. DelegateHandler를 사용하여 클라이언트 쪽에서 JWT 작업을하고있는 것을 볼 수 있습니다. 그러나 여기서는 적절하지 않다고 생각합니다. 그것은 들어오는 응답, 나가는 요청을 만지지 않습니다.

public static HttpClient GetHttpClient(bool WithAuthToken = true) 
{ 
    App thisApp = (App)System.Windows.Application.Current; 

    //HttpClient http = new HttpClient(); 
    HttpClient http = HttpClientFactory.Create(new JWTExpirationHandler()); 

    http.BaseAddress = new Uri(thisApp.WebAPI_BaseUrl); 
    http.DefaultRequestHeaders.Accept.Clear(); 
    http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

    if(WithAuthToken) 
     http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", JWT); 

    return http; 

} 

들어오는 요청이 "application/json"및 UTF-8의 콘텐츠 유형임을 확인했습니다.

웹 서버에 두 개의 DelegatingHandler가 있지만 문제가없는 것 같습니다. 첫 번째 맨 위에있는 ReadAsAsync()를 끝내면 null이기도합니다. ReadAsStringAsync()는 JSON을 반환합니다.

그래서 ... 내가 뭘 잘못하고 있니? 다시 말하지만,이 작업은 훌륭했습니다. 무언가가 바뀌 었습니다. 모두 POST와 PUT이 이렇게 부러졌습니다.

내 클래스에서 [Serializable]을 제거한다고 말하는 링크를 보았습니다. 그러나 이것들은 여러 곳에서 사용하는 Entity Framework 클래스이며, 그렇게하고 싶지 않습니다.

마침내 내가 우편 게시자를 통해이 업데이트 PUT을 호출하면 작동합니다. 내 자신의 클라이언트에서 HttpRequests 비교

UPDATE
, 그리고 우체부에서, 나는 전자는 "청크"하고 후자는없는 것을 알 수있다. 이것은 중요한 단서처럼 보입니다.나는 다른 사람들이 같은 취급을 참조하십시오

ASP.NET Web Api - the framework is not converting JSON to object when using Chunked Transfer Encoding

내가 오프 청크 설정하는 방법의 명확한 표시를 찾을 수 없습니다. I 을 수행하십시오. 청킹을 해제하는 속성이 있음을 알지만 그렇게하면 도움이되지 않습니다.

질문 : "선택"을 청크로 트리거하는 것은 무엇입니까? 클라이언트가이 작업을 수행하기로 선택 했습니까? 아니면 컨트롤러 또는 두 작업 사이의 일부 협상입니까?

+0

WPF 앱에서 사용하는 User 개체가 WebApi 끝점의 개체와 일치합니까? 당신은 최근에 한 일을 말해줍니다. 모델을 업데이트 했습니까? 한 가지 요점으로, 저는 EF Entity Model을 Api Controller에서 보내지 않는 것이 좋습니다. 그것을 단순한 Dto에 맵핑하고 보내십시오. 여기에 좋은 블로그가 있습니다 .http : //codethug.com/2015/02/13/web-api-deep-dive-dto-transformations-and- automapper-part-5-of-6/이것은 문제가되지 않을 수도 있지만 다루기가 더 쉽고 안전하며 – MartinM

+0

을 다루는 데이터에 대한 명확한 그림을 제공합니다. Thanks, @MartinMilsom. User 개체는 동일합니다. .edmx 파일이 하나의 프로젝트에 있고 .tt 파일이 다른 모든 프로젝트가 참조하는 "공통"프로젝트에 있도록 솔루션을 정리했습니다. 따라서 .edmx를 변경하면 개체가 변경되지만 솔루션의 모든 프로젝트는 동일한 User/다른 개체를 공유합니다. – TomK

+0

나는 본다. 그러나 Api를 통해 Entity를 보내면 변경으로 인해 문제가 발생할 수 있습니다. 예를 들어 json/xml serialiser가 직렬화를 해제하는 방법을 모르는 속성이 추가되거나 생성자에 일부 논리를 추가했거나 생성자를 개인용으로 만든 경우 등이 모두 예일뿐입니다. 그러나 잘못 될 수있는 제비가 있습니다. json 문자열을 수동으로 유형을 비 직렬화하려는 경우 - 오류가 있는지 확인하는 것이 좋습니다. JsonConvert.DeserializeObject (jsonString); – MartinM

답변

0

길었습니다. 그것이 거기에 도착하는 방법

모르겠지만, 내 .csproj에서 나는이 있었다 :

<Reference Include="System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> 
    <HintPath>..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath> 
    <Private>True</Private> 
</Reference> 

보다는이 :

<Reference Include="System.Net.Http" /> 

그리고이 있었다 제의 App.config의를 :

<dependentAssembly> 
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> 
    <bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" /> 
    </dependentAssembly> 
    <dependentAssembly> 
    <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> 
    <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> 
    </dependentAssembly> 

... 오히려 하지이를 .... 나는이 물건이 필요하지 않았다. 나는 방금 그것을 꺼냈다.

관련 문제