如何使用WCF WebApi的HttpClient发布POCO

cki*_*tel 5 wcf wcf-client wcf-web-api

我正在通过NuGet(pkg版本0.3.0)使用WCF WebApi堆栈(预览4),似乎无法弄清楚如何使用"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
...
Run Code Online (Sandbox Code Playgroud)

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)
...
Run Code Online (Sandbox Code Playgroud)

这是使用NuGet 0.3.0包.

我试过添加<Serializable()>甚至<DataContract()>MyInfo,但这没有帮助.我只是做错了吗?

我在StackOverflow上找到了这篇文章,看起来有人做了类似我上面做的事情.我甚至复制了他的工作(猜测他的Machine对象是一个像我一样简单的POCO MyInfo)并遇到了同样的"无法序列化"异常.

cki*_*tel 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
Run Code Online (Sandbox Code Playgroud)

它开始工作了.我想这是有道理的.出于某种原因,我认为内置了某种默认的媒体类型优先级,因此您不必每次都指出媒体类型.也许有,但我还在做错什么?

更新:

我的原始问题实际上与媒体类型无关,即使这实际上确实解决了问题.当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
Run Code Online (Sandbox Code Playgroud)

一旦MyInfo移到外面Module,错误就不再发生了.还值得注意的是,虽然不再需要媒体类型来防止异常,但缺少它会导致没有Content-Type标头,这可能无法在服务器端飞行,因为服务器可能不知道如何反序列化消息体.在我的情况下,我需要保留媒体类型,以便请求包含Content-Type: application/xml服务器的标题.