【问题标题】:F# cannot post to web api?F# 不能发布到 web api?
【发布时间】:2022-02-07 01:41:08
【问题描述】:

我有以下代码可以发布到 web api。

[<CLIMutable>]
type MyModel = { FileName:string; Period:DateTime; DownloadedTime:DateTimeOffset; Url:string; }

let PostDownload (filepath, date, url) = 
  async {
    try
        use client = new HttpClient()
        let content = { FileName = filepath; Period = date; DownloadedTime = DateTimeOffset.Now; Url = url }
        let! response = Async.AwaitTask(client.PostAsJsonAsync("http://localhost:5000/api/DownloadedFiles", content))
    with 
    | ex -> logger.Error(ex, "Exception: " + ex.Message)
  } |> Async.Start

该服务具有以下代码,调试器显示downloadedFile 的所有字段都是默认值(空值或值类型的最小值)。

    [HttpPost]
    public void Post([FromBody]DownloadedFile downloadedFile)
    {
        try
        {
            _context.DownloadedFile.Add(downloadedFile);
            _context.SaveChanges();
        }
        catch (Exception ex) { ...... }
    }

fiddler 显示 F# 代码(或者 PostAsJsonAsync 无法处理 F# 可变记录类型?)在字段名称末尾添加了 @

{"FileName@":"test","Period@":"2100-01-01T00:00:00","DownloadedTime@":"2016-08-18T15:50:37.5004391-04:00" ,"Url@":"测试"}

【问题讨论】:

标签: c# asp.net-web-api f# webclient


【解决方案1】:

我不知道你从哪里得到HttpClient.PostAsJsonAsync,因为它不在我目前正在查看的HttpClient 版本上。不过,我通常使用这个扩展,它对我有用:

type HttpClient with
    member this.PostAsJsonAsync (requestUri : string, value : obj) =
        let json = string value
        let content = new StringContent (json)
        content.Headers.ContentType <-
            Headers.MediaTypeHeaderValue "application/json"
        this.PostAsync (requestUri, content)

【讨论】:

  • PostAsJasonAsync 在 HttpClientExtensions 中:msdn.microsoft.com/en-us/library/hh944521(v=vs.118).aspx
  • 我尝试了代码(使用PostAsync而不是PostAsJasonAsync。但它仍然失败,提琴手显示http post body现在是FSI_0004+MyFileModel
  • 您会看到类名 (FSI_0004+MyFileModel),因为当您在尚未覆盖该方法的类上调用 ToString() 时会发生这种情况。使用理解 F# Records 的库(例如 JSON.NET 的当前版本)将对象显式转换为 JSON 将允许 Mark 的示例工作。
【解决方案2】:

我刚刚遇到了这个问题,并浪费了几个小时来解决它。 似乎 HttpClient.PostAsJsonAsync 中使用的序列化程序不能很好地处理 fsharp 类型。 @ 符号问题也不容易用谷歌搜索。 然而,使用以下代码似乎可行:

task {
  let content = JObject.FromObject({ Id = "foo" }).ToString()
  let! response = client.PostAsync("url", new StringContent(content, Encoding.UTF8, "application/json"))
  return "Hello world"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 2013-10-06
    • 2019-05-10
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多