如何使用WCF WebApi的HttpClient发布POCO

时间:2011-07-27 18:49:50

标签: wcf wcf-client wcf-web-api

我正在通过NuGet(pkg版本0.3.0)使用WCF WebApi堆栈(预览4),似乎无法弄清楚如何使用HttpClient“POST a POCO”。

鉴于以下内容:

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上找到了this post,看起来有人做了类似我上面做的事情。我甚至重复了他的工作(猜测他的Machine对象是一个简单的POCO,就像我的MyInfo那样)并遇到了同样的“无法序列化”的异常。

1 个答案:

答案 0 :(得分:5)

我最终自己找到了问题。我错过了媒体类型。我将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标头。