我是新來的F#,並試圖翻譯一些C#ASP.NET核心代號爲F#在ASP.NET異步控制器方法F#的語法核心
即使我得到它的工作,我似乎無法弄清楚如何使控制器操作異步。這些方法在注入的Commands對象和Queries對象上調用異步代碼。命令和查詢目前在C#中實現。
因此,例如,一對夫婦的異步C#控制器方法是:
public async Task<IEnumerable<ToDoItem>> Get()
{
return await queries.GetAll();
}
[HttpGet("{id}", Name = "GetTodo")]
public async Task<IActionResult> GetById(string id)
{
var item = await queries.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
public async Task<IActionResult> Create([FromBody] ToDoItem item)
{
if (item == null)
{
return BadRequest();
}
if (string.IsNullOrEmpty(item.Id)) item.Id = Guid.NewGuid().ToString();
await commands.Add(item);
return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}
,我已經翻譯那些F#像這樣:
[<HttpGet>]
member __.Get() =
__.Queries.GetAll() // this should be awaited
[<HttpGet("{id}", Name = "GetFSTodo")>]
member __.GetToDoItem(id) =
let data = __.Queries.Find(id) // this should be awaited
if isNull data
then __.NotFound() :> IActionResult
else
new ObjectResult(data) :> IActionResult
[<HttpPost>]
member __.Create([<FromBody>] item:ToDoItem) =
item.Id <- Guid.NewGuid().ToString()
(__.Commands.Add(item)) |> ignore // this should be awaited
let rv = new RouteValueDictionary()
rv.Add("id",item.Id)
__.CreatedAtRoute("GetTodo", rv, item) :> IActionResult
這些方法的工作,但我認爲他們是沒有正確完成,因爲他們沒有在等待查詢和命令的異步調用。我經歷了幾個小時的試驗和錯誤,但是我做出的每一次嘗試使控制器方法異步結果都不會返回任何數據到瀏覽器,即使它們返回200狀態代碼。你可以看到我的一些嘗試在F# controller
中註釋掉了。希望一些F#guru可以幫助我正確地翻譯這些方法。目前在F#和ASP.NET Core方面存在一些非常糟糕的工具問題,這使得像我這樣的新手變得更加困難。我在readme
提到的這些問題中有代碼的一些額外的方法,但我想如果我能學會如何解決這些方法,然後同樣的解決方案將可能適用於其他方法。
該代碼位於公共存儲庫中,因此只要您擁有最新的VS更新和最新的ASP,您就可以在VS 2015中輕鬆進行試用。NET核心工具安裝
UPDATE:
感謝鏈接後由馬克·西曼,我能夠通過使用輔助函數
let asyncReturn x = async { return x }
得到這個方法異步
[<HttpGet("{id}", Name = "GetFSTodo")>]
member __.GetToDoItem(id) =
async {
let! data = __.Queries.Find(id) |> asyncReturn
if isNull data
then return __.NotFound() :> IActionResult
else
return new ObjectResult(data) :> IActionResult }
|> Async.StartAsTask
工作
我仍在努力用這種方法
[<HttpGet>]
member __.Get() =
async {
let! data = __.Queries.GetAll() |> asyncReturn
return data }
|> Async.StartAsTask
這是從這個C#方法翻譯:
[HttpGet]
public async Task<IEnumerable<ToDoItem>> Get()
{
return await queries.GetAll();
}
異步F#方法的作品,但它產生比C#版本
C#
[{"id":"4f4e1596-6a48-4854-9982-7a2568aa1b1b","title":"add input validation","isDone":false,"dateAdded":"2016-09-20T21:16:04.8791044Z"},{"id":"9929b657-6a53-40b6-8c1c-1e4d0db593cd","title":"make F# controller async","isDone":false,"dateAdded":"2016-09-21T19:36:44.6650776Z"},{"id":"5bb5f544-6289-4051-ad65-d0dc016128e7","title":"learn F# basics","isDone":true,"dateAdded":"2016-09-22T11:59:00"},{"id":"e5e06118-c49f-496a-8175-9719ea72beed","title":"monkey business","isDone":false,"dateAdded":"2016-09-22T16:22:20.3133161Z"},{"id":"af0db8f2-6b49-4e31-86fa-e27c8e091f42","title":"funky bidness","isDone":false,"dateAdded":"2016-09-22T16:23:35.1175195Z"}]
F#
{"result":[{"id":"4f4e1596-6a48-4854-9982-7a2568aa1b1b","title":"add input validation","isDone":false,"dateAdded":"2016-09-20T21:16:04.8791044Z"},{"id":"9929b657-6a53-40b6-8c1c-1e4d0db593cd","title":"make F# controller async","isDone":false,"dateAdded":"2016-09-21T19:36:44.6650776Z"},{"id":"5bb5f544-6289-4051-ad65-d0dc016128e7","title":"learn F# basics","isDone":true,"dateAdded":"2016-09-22T11:59:00"},{"id":"e5e06118-c49f-496a-8175-9719ea72beed","title":"monkey business","isDone":false,"dateAdded":"2016-09-22T16:22:20.3133161Z"},{"id":"af0db8f2-6b49-4e31-86fa-e27c8e091f42","title":"funky bidness","isDone":false,"dateAdded":"2016-09-22T16:23:35.1175195Z"}],"id":65,"exception":null,"status":5,"isCanceled":false,"isCompleted":true,"creationOptions":0,"asyncState":null,"isFaulted":false}
不同的JSON輸出,所以我仍然可以使用上如何一些幫助使F#版本能產生預期的輸出
嘗試Async.AwaitTask – Ringil
您可以在此博客末尾看到一個異步控制器操作示例:http ://blog.ploeh.dk/2016/04/11/async-as-surrogate-io這有幫助嗎? –
@ mark-seemann謝謝!我已經得到了一些進展感謝您的帖子,並已更新我的問題,希望進一步的洞察 –