iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 8
4

我們打算用Azure Functions開發一個交友任務提示表後端API,類似TODO LIST的管理自己在交友時,應該完成的必要項目

大概是下面那個樣子的

理想中的UI畫面:

實際雛型影片:

而我們的REST API有下面幾個

  1. 新增交友任務 api/missions (POST)
  2. 取得交友任務列表 api/missions (GET)
  3. 刪除交友任務 api/mission/{id} (DELETE)
  4. 編輯交友任務 api/mission/{id} (PUT)

接下來我們直接進入正題,來開發程式囉!

前後端原始程式碼下載:https://github.com/hatsukiotowa/AzureFunctionsRestAPI

建立一個TODO Model: Models.cs

裡面有TaskId,建立時間,任務內容,是否完成

public class Todo
{
    public string Id { get; set; } = Guid.NewGuid().ToString("n");
    public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
    public string MissionDescription { get; set; }
    public bool IsCompleted { get; set; }
}
public class TodoCreateModel
{
    public string MissionDescription { get; set; }
}
public class TodoUpdateModel
{
    public string MissionDescription { get; set; }
    public bool IsCompleted { get; set; }
}


建立CREATE TODO ITEM Azure Functions,編輯Functions.cs程式碼

1. 新增交友任務 api/missions (POST)


using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using System.Threading.Tasks;
using static ServerlessFuncs.Todo;
using System.Collections.Generic;
using System.Linq;

public static class TodoApi
{
    static List<Todo> items = new List<Todo>();

    [FunctionName("CreateTodo")]
    public static async Task<IActionResult> CreateTodo(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "missions")]HttpRequest req, 
    TraceWriter log)
    {
        log.Info("Creating a new todo list item");

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        var input = JsonConvert.DeserializeObject<TodoCreateModel>(requestBody);

        var todo = new Todo() { MissionDescription = input.MissionDescription };
        items.Add(todo);
        return new OkObjectResult(todo);
    }
}

接下來說明程式碼

  • 因為我們這邊先不串接資料庫,先用一個List暫存新增的TODO ITEM
static List<Todo> items = new List<Todo>();
items.Add(todo);
var todo = new Todo() { MissionDescription = input.MissionDescription };
  • 指定FunctionName為CreateTodo
[FunctionName("CreateTodo")]
  • 非同步處理,設定Http Trigger,限定只有"POST" METHOD,REST API指定ROUTE,以及設定Logger
public static async Task<IActionResult> CreateTodo(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "missions")]HttpRequest req, 
TraceWriter log)

  • 非同步處理response,並且將json資料deserialize
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var input = JsonConvert.DeserializeObject<TodoCreateModel>(requestBody);
  • 會回傳一個json object(200)
return new OkObjectResult(todo);

來測試一下寫好的程式碼吧!

(POST)http://localhost:7071/api/missions

很好,已經成功新增資料到List裡面喔!


接下來我們要取得任務列表

2. 取得交友任務列表 api/missions (GET)

這邊程式碼很簡單,我們把Method改成get,把回傳值改成OkObjectResult(items),就能取得任務列表Json資料囉!

[FunctionName("GetTodos")]
public static async Task<IActionResult> GetTodos(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "missions")]HttpRequest req, 
TraceWriter log)
{
    log.Info("Getting todo list items");
    return new OkObjectResult(items);
}

(GET)http://localhost:7071/api/missions

3. 更新交友任務列表 api/mission/{id} (PUT)

[FunctionName("UpdateTodo")]
public static async Task<IActionResult> UpdateTodo(
[HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "mission/{id}")]HttpRequest req, 
TraceWriter log, string id)
{
    var todo = items.FirstOrDefault(t => t.Id == id);
    if (todo == null)
    {
        return new NotFoundResult();
    }

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    var updated = JsonConvert.DeserializeObject<TodoUpdateModel>(requestBody);

    todo.IsCompleted = updated.IsCompleted;
    if (!string.IsNullOrEmpty(updated.MissionDescription))
    {
        todo.MissionDescription = updated.MissionDescription;
    }
    return new OkObjectResult(todo);
}

測試結果,修改成功!

(PUT)http://localhost:7071/api/mission/770eb6356720445da60a6ec0098a0dd2

4. 刪除交友任務列表 api/mission/{id} (DELETE)

[FunctionName("DeleteTodo")]
public static async Task<IActionResult> DeleteTodo(
[HttpTrigger(AuthorizationLevel.Anonymous, "delete", 
Route = "mission/{id}")]HttpRequest req, 
TraceWriter log, 
string id)
{
    var todo = items.FirstOrDefault(t => t.Id == id);
    if (todo == null)
    {
        return new NotFoundResult();
    }
    items.Remove(todo);
    return new OkResult();
}

測試結果,刪除成功!

(DELETE)http://localhost:7071/api/mission/567bbeb347c44e78b7829d2a1e1ab691

之後再接上前端以及資料庫,就能完成我們期望中的交友任務管理功能囉!

在這邊我們用一個簡單的Vue打造前端的頁面,串接我們寫好的後端API

而我們Local端測試時,因Javascript針對跨來源HTTP請求有保護機制(CORS),我們要先針對程式碼進行微調,設定Local端的CORS(cross-origin HTTP request)。

如果我們沒進行設定,直接將前端Javascript串上後端API,會產生以下CORS跨域請求的錯誤

Failed to load http://localhost:7071/api/missions: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

好的,那我們來針對CORS進行檔案的修改吧!

修改local.settings.json

針對原先檔案,加入以下這行

  "Host": {
    "CORS": "*"
  }

注意:此設定僅對Local測試有效

加上之後我們就沒有再遇到錯誤囉!前後端串接成功!
前後端一串起來,是不是很有成就感呢!你也成功用Azure Functions打造自己的REST API囉!

相關的實作畫面:修改交友任務(PUT)/api/mission/{id}

前後端原始程式碼下載:https://github.com/hatsukiotowa/AzureFunctionsRestAPI

我們今天使用Functions打造了CRUD四兄弟(新增/修改/刪除/查詢),但是我們尚未串接上Storage。

在下一個章節我們將串接Azure Table Storage,並簡單介紹Azure Table Storage的概念及使用方法,讓大家能快速將自己的RESTful API串上資料庫喔!

串接資料庫快速連結:(實作)交友任務管理Functions⚡ + 串接Azure Table Storage


參考


上一篇
[DAY07] 用地表最強開發工具Visual Studio 2017開發Azure Functions⚡
下一篇
[DAY09] (實作)交友任務管理Functions⚡ + 串接Azure Table Storage
系列文
30天手把手帶你趣學Azure☁️-初學者也能動手實作🙌🏻30

尚未有邦友留言

立即登入留言