如何使用 WCF WebApi 的 HttpClient 发布 POCO

发布于 2024-11-26 13:26:44 字数 2528 浏览 1 评论 0原文

我通过 NuGet(pkg 版本 0.3.0)使用 WCF WebApi 堆栈(预览版 4),但似乎无法弄清楚如何使用 HttpClient 来“发布 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)
...

This is using the NuGet 0.3.0 package。

我尝试将 甚至 添加到 MyInfo 中,但没有成功帮助。我只是做错了什么吗?

我在 StackOverflow 上找到了这篇文章,它看起来像某人正在做与我上面所做的类似的事情。我什至重复了他的工作(猜测他的 Machine 对象是一个简单的 POCO,就像我的 MyInfo 一样)并遇到了相同的“无法序列化”异常。

I'm using the WCF WebApi stack (Preview 4) via NuGet (pkg version 0.3.0) and cannot seem to figure out how to "POST a POCO" using HttpClient.

Given the following:

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
...

When the Post method is called, I get the following exception:

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)
...

This is using the NuGet 0.3.0 package.

I've tried adding <Serializable()> and even <DataContract()> to MyInfo, but that didn't help. Am I just doing something wrong?

I found this post here on StackOverflow where it looks like someone is doing something similar to what I did above. I've even duplicated his work (guessing that his Machine object was a simple POCO like my MyInfo is) and ran into the same "cannot serialize" exception.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ζ澈沫 2024-12-03 13:26:44

我最终自己发现了问题。我缺少媒体类型。我将 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 标头。

I ended up finding the problem myself. I was missing the media type. I changed the Post method to look like:

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

and it started working. I guess that makes sense. For some reason, I thought that there was some sort of default media type precedence built-in so that you didn't have to go out of your way to specify the media type each time. Maybe there is, but I'm still doing something wrong?

Update:

My original problem actually had nothing to do with the media type, even though that actually did fix/workaround the problem. The problem seems to happen when MyInfo is nested inside of a Module like this.

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

Once MyInfo moved outside of the Module, the error no longer happens. It's also worth noting that while the media type is no longer required to prevent the exception, the lack of it results in no Content-Type header, which may not fly server-side as the server may not know how to deserialize the message body. In my case, I needed to leave the media type in so that the request would include a Content-Type: application/xml header for the server's sake.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文