Как разместить POCO с помощью HttpClient WCA WebApi - PullRequest
5 голосов
/ 27 июля 2011

Я использую стек WCA WebApi (Preview 4) через NuGet (версия 0.3.0 pkg) и не могу понять, как "POST a POCO" использовать HttpClient.

Учитывая следующее:

Public Class MyInfo
    Public Property MyDate As DateTime
    Public Property MyId As Guid
End Class

...
Dim value = New MyInfo With {.MyDate = Today, .MyId = Guid.NewGuid()}

Using client as New HttpClient(baseUri)
    Using response = client.Post(requestUri, New ObjectContent(Of MyInfo)(value))
        ' Do stuff
    End Using
End Using
...

Когда вызывается метод Post, я получаю следующее исключение:

The 'XmlSerializer' serializer cannot serialize the type 'MyInfo'.

at Microsoft.ApplicationServer.Http.XmlMediaTypeFormatter.GetSerializerForType(Type type)
at Microsoft.ApplicationServer.Http.XmlMediaTypeFormatter.OnWriteToStream(Type type, Object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext context)
at Microsoft.ApplicationServer.Http.MediaTypeFormatter.WriteToStream(Type type, Object instance, Stream stream, HttpContentHeaders contentHeaders, TransportContext context)
at Microsoft.ApplicationServer.Http.ObjectContent.WriteToStreamInternal(Stream stream, TransportContext context)
at Microsoft.ApplicationServer.Http.ObjectContent.SerializeToStream(Stream stream, TransportContext context)
at System.Net.Http.HttpContent.LoadIntoBuffer(Int32 maxBufferSize)
at System.Net.Http.HttpClientChannel.PrepareWebRequestForContentUpload(HttpWebRequest webRequest, HttpRequestMessage request)
at System.Net.Http.HttpClientChannel.CreateAndPrepareWebRequest(HttpRequestMessage request)
at System.Net.Http.HttpClientChannel.Send(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.Send(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.Send(HttpRequestMessage request)
at System.Net.Http.HttpClient.Post(Uri requestUri, HttpContent content)
at System.Net.Http.HttpClient.Post(String requestUri, HttpContent content)
...

Используется пакет NuGet 0.3.0.

Я пытался добавить <Serializable()> и даже <DataContract()> к MyInfo, но это не помогло. Я просто что-то делаю не так?

Я нашел этот пост здесь, в StackOverflow, где, похоже, кто-то делает что-то похожее на то, что я делал выше. Я даже продублировал его работу (предполагая, что его Machine объект был простым POCO, как мой MyInfo is) и столкнулся с тем же исключением «не может сериализовать».

1 Ответ

5 голосов
/ 28 июля 2011

Я сам нашел проблему. Я пропустил тип носителя. Я изменил метод Post, чтобы он выглядел так:

Using client as New HttpClient(baseUri)
    Using response = client.Post(requestUri, New ObjectContent(Of MyInfo)(value, "text/xml"))
        ' Do stuff
    End Using
End Using

и он начал работать. Я думаю, это имеет смысл. По какой-то причине я подумал, что есть какой-то встроенный тип приоритета медиа по умолчанию, так что вам не нужно каждый раз указывать тип медиа. Может быть, есть, но я все еще делаю что-то не так?

Обновление:

Моя первоначальная проблема на самом деле не имела ничего общего с типом носителя, хотя это и решало проблему. Кажется, проблема возникает, когда MyInfo вложен внутрь Module, как это.

Module Module1

    Sub Main()
        Dim value = New MyInfo With {.MyDate = Today, .MyId = Guid.NewGuid()}
        Dim payload As HttpContent = New ObjectContent(Of MyInfo)(value)

        Using client as New HttpClient(baseUri)
            Using response = client.Post(requestUri, New ObjectContent(Of MyInfo)(value))
                ' Do stuff
            End Using
        End Using
    End Sub

    Public Class MyInfo
        Public Property MyDate As DateTime
        Public Property MyId As Guid
    End Class

End Module

После того, как MyInfo вышел за пределы Module, ошибка больше не возникает. Стоит также отметить, что хотя тип носителя больше не требуется для предотвращения исключения, его отсутствие приводит к отсутствию заголовка Content-Type, который может не выполняться на стороне сервера, поскольку сервер может не знать, как десериализовать тело сообщения. В моем случае мне нужно было оставить тип носителя таким образом, чтобы запрос содержал заголовок Content-Type: application/xml для сервера.

...