使用 ASP.NET Core 為本機(jī)移動應(yīng)用創(chuàng)建后端服務(wù)

2019-04-17 08:57 更新

移動應(yīng)用可與 ASP.NET Core 后端服務(wù)通信。 有關(guān)從 iOS 模擬器和 Android 仿真程序連接本地 Web 服務(wù)的說明,請參閱從 iOS 模擬器和 Android 仿真程序連接到本地 Web 服務(wù)。

查看或下載后端服務(wù)代碼示例

本機(jī)移動應(yīng)用示例

本教程演示如何創(chuàng)建使用 ASP.NET Core MVC 支持本機(jī)移動應(yīng)用的后端服務(wù)。 它使用 Xamarin Forms ToDoRest 應(yīng)用 作為其本機(jī)客戶端,其中包括 Android、 iOS、 Windows Universal 和 Window Phone 設(shè)備的單獨本機(jī)客戶端。 你可以遵循鏈接中的教程來創(chuàng)建本機(jī)應(yīng)用程序(并安裝需要的免費 Xamarin 工具),以及下載 Xamarin 示例解決方案。 Xamarin 示例包含一個 ASP.NET Web API 2 服務(wù)項目,使用本文中的 ASP.NET Core 應(yīng)用替換(客戶端無需進(jìn)行任何更改)。

在 Android 智能手機(jī)上運(yùn)行的 ToDoRest 應(yīng)用程序

功能

ToDoRest 應(yīng)用支持列出、 添加、刪除和更新待辦事項。 每個項都有一個 ID、 Name(名稱)、Notes(說明)以及一個指示該項是否已完成的屬性 Done。

待辦事項的主視圖如上所示,列出每個項的名稱,并使用復(fù)選標(biāo)記指示它是否已完成。

點擊 + 圖標(biāo)打開“添加項”對話框:

“添加項”對話框

點擊主列表屏幕上的項將打開一個編輯對話框,在其中可以修改項的名稱、 說明以及是否完成,或刪除項目:

“編輯項”對話框

此示例默認(rèn)配置為使用托管在 developer.xamarin.com上的后端服務(wù),允許只讀操作。 若要使用在你計算機(jī)上運(yùn)行的下一節(jié)創(chuàng)建的 ASP.NET Core 應(yīng)用對其進(jìn)行測試,你需要更新應(yīng)用程序的 RestUrl 常量。 導(dǎo)航到 ToDoREST 項目,然后打開 Constants.cs 文件。 使用包含計算機(jī) IP 的 URL 地址替換 RestUrl(不是 localhost 或 127.0.0.1,因為此地址用于從設(shè)備模擬器中,而不是從你的計算機(jī)中訪問)。 請包括端口號 (5000)。 為了測試你的服務(wù)能否在設(shè)備上正常運(yùn)行,請確保沒有活動的防火墻阻止訪問此端口。

C#

// URL of REST service (Xamarin ReadOnly Service)
//public static string RestUrl = "http://developer.xamarin.com:8081/api/todoitems{0}";

// use your machine's IP address
public static string RestUrl = "http://192.168.1.207:5000/api/todoitems/{0}";

創(chuàng)建 ASP.NET Core 項目

在 Visual Studio 中創(chuàng)建一個新的 ASP.NET Core Web 應(yīng)用程序。 選擇 Web API 模板和 No Authentication(無身份驗證)。 將項目命名為 ToDoApi。

“新建 ASP.NET Web 應(yīng)用程序”對話框,其中已選中 Web API 項目模板

對于向端口 5000 進(jìn)行的請求,應(yīng)用程序均需作出響應(yīng)。 更新 Program.cs,使其包含 .UseUrls("http://*:5000"),以便實現(xiàn)以下操作:

C#

var host = new WebHostBuilder()
    .UseKestrel()
    .UseUrls("http://*:5000")
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

 備注

請確保直接運(yùn)行應(yīng)用程序,而不是在 IIS Express 后運(yùn)行,因為在默認(rèn)情況下,后者會忽略非本地請求。 從命令提示符處運(yùn)行 dotnet run,或從 Visual Studio 工具欄中的“調(diào)試目標(biāo)”下拉列表中選擇應(yīng)用程序名稱配置文件。

添加一個模型類來表示待辦事項。 使用 [Required] 屬性標(biāo)記必需字段:

C#

using System.ComponentModel.DataAnnotations;

namespace ToDoApi.Models
{
    public class ToDoItem
    {
        [Required]
        public string ID { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Notes { get; set; }

        public bool Done { get; set; }
    }
}

API 方法需要通過某種方式處理數(shù)據(jù)。 使用原始 Xamarin 示例所用的 IToDoRepository 接口:

C#

using System.Collections.Generic;
using ToDoApi.Models;

namespace ToDoApi.Interfaces
{
    public interface IToDoRepository
    {
        bool DoesItemExist(string id);
        IEnumerable<ToDoItem> All { get; }
        ToDoItem Find(string id);
        void Insert(ToDoItem item);
        void Update(ToDoItem item);
        void Delete(string id);
    }
}

在此示例中,該實現(xiàn)僅使用一個專用項集合:

C#

using System.Collections.Generic;
using System.Linq;
using ToDoApi.Interfaces;
using ToDoApi.Models;

namespace ToDoApi.Services
{
    public class ToDoRepository : IToDoRepository
    {
        private List<ToDoItem> _toDoList;

        public ToDoRepository()
        {
            InitializeData();
        }

        public IEnumerable<ToDoItem> All
        {
            get { return _toDoList; }
        }

        public bool DoesItemExist(string id)
        {
            return _toDoList.Any(item => item.ID == id);
        }

        public ToDoItem Find(string id)
        {
            return _toDoList.FirstOrDefault(item => item.ID == id);
        }

        public void Insert(ToDoItem item)
        {
            _toDoList.Add(item);
        }

        public void Update(ToDoItem item)
        {
            var todoItem = this.Find(item.ID);
            var index = _toDoList.IndexOf(todoItem);
            _toDoList.RemoveAt(index);
            _toDoList.Insert(index, item);
        }

        public void Delete(string id)
        {
            _toDoList.Remove(this.Find(id));
        }

        private void InitializeData()
        {
            _toDoList = new List<ToDoItem>();

            var todoItem1 = new ToDoItem
            {
                ID = "6bb8a868-dba1-4f1a-93b7-24ebce87e243",
                Name = "Learn app development",
                Notes = "Attend Xamarin University",
                Done = true
            };

            var todoItem2 = new ToDoItem
            {
                ID = "b94afb54-a1cb-4313-8af3-b7511551b33b",
                Name = "Develop apps",
                Notes = "Use Xamarin Studio/Visual Studio",
                Done = false
            };

            var todoItem3 = new ToDoItem
            {
                ID = "ecfa6f80-3671-4911-aabe-63cc442c1ecf",
                Name = "Publish apps",
                Notes = "All app stores",
                Done = false,
            };

            _toDoList.Add(todoItem1);
            _toDoList.Add(todoItem2);
            _toDoList.Add(todoItem3);
        }
    }
}

在 Startup.cs 中配置該實現(xiàn):

C#

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddSingleton<IToDoRepository,ToDoRepository>();
}

現(xiàn)可創(chuàng)建 ToDoItemsController。

 提示

有關(guān)創(chuàng)建 Web API 的詳細(xì)信息,請參閱使用 ASP.NET Core MVC 和 Visual Studio 生成首個 Web API。

創(chuàng)建控制器

在項目中添加新控制器 ToDoItemsController。 它應(yīng)繼承 Microsoft.AspNetCore.Mvc.Controller。 添加 Route 屬性以指示控制器將處理路徑以 api/todoitems 開始的請求。 路由中的 [controller] 標(biāo)記會被控制器的名稱代替(省略 Controller 后綴),這對全局路由特別有用。 詳細(xì)了解 路由。

控制器需要 IToDoRepository 才能正常運(yùn)行;通過控制器的構(gòu)造函數(shù)請求該類型的實例。 在運(yùn)行時,此實例將使用框架對 依賴關(guān)系注入 的支持來提供。

C#

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ToDoApi.Interfaces;
using ToDoApi.Models;

namespace ToDoApi.Controllers
{
    [Route("api/[controller]")]
    public class ToDoItemsController : Controller
    {
        private readonly IToDoRepository _toDoRepository;

        public ToDoItemsController(IToDoRepository toDoRepository)
        {
            _toDoRepository = toDoRepository;
        }

此 API 支持四個不同的 HTTP 謂詞來執(zhí)行對數(shù)據(jù)源的 CRUD(創(chuàng)建、讀取、更新、刪除)操作。 最簡單的是讀取操作,它對應(yīng)于 HTTP GET 請求。

讀取項目

要請求項列表,可對 List 方法使用 GET 請求。 [HttpGet] 方法的 List 屬性指示此操作應(yīng)僅處理 GET 請求。 此操作的路由是在控制器上指定的路由。 你不一定必須將操作名稱用作路由的一部分。 你只需確保每個操作都有唯一的和明確的路由。 路由屬性可以分別應(yīng)用在控制器和方法級別,以此生成特定的路由。

C#

[HttpGet]
public IActionResult List()
{
    return Ok(_toDoRepository.All);
}

List 方法返回 200 OK 響應(yīng)代碼和所有 ToDo 項,并序列化為 JSON 。

你可以使用多種工具測試新的 API 方法,如 Postman,如此處所示:

Postman 控制臺,其中顯示一個 todoitem 的 GET 請求,以及顯示所返回的三個項目的 JSON 的響應(yīng)正文

創(chuàng)建項目

按照約定,創(chuàng)建新數(shù)據(jù)項映射到 HTTP POST 謂詞。 Create 方法具有應(yīng)用于該對象的 [HttpPost]屬性,并接受 ToDoItem 實例。 由于 item 參數(shù)將在 POST 的正文中傳遞,因此該參數(shù)用 [FromBody] 屬性修飾。

在該方法中,會檢查項的有效性和之前是否存在于數(shù)據(jù)存儲,并且如果沒有任何問題,則使用存儲庫添加。 檢查 ModelState.IsValid 將執(zhí)行 模型驗證,應(yīng)該在每個接受用戶輸入的 API 方法中執(zhí)行此步驟。

C#

[HttpPost]
public IActionResult Create([FromBody] ToDoItem item)
{
    try
    {
        if (item == null || !ModelState.IsValid)
        {
            return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
        }
        bool itemExists = _toDoRepository.DoesItemExist(item.ID);
        if (itemExists)
        {
            return StatusCode(StatusCodes.Status409Conflict, ErrorCode.TodoItemIDInUse.ToString());
        }
        _toDoRepository.Insert(item);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotCreateItem.ToString());
    }
    return Ok(item);
}

示例中使用一個枚舉,后者包含傳遞到移動客戶端的錯誤代碼:

C#

public enum ErrorCode
{
    TodoItemNameAndNotesRequired,
    TodoItemIDInUse,
    RecordNotFound,
    CouldNotCreateItem,
    CouldNotUpdateItem,
    CouldNotDeleteItem
}

使用 Postman 測試添加新項,選擇 POST 謂詞并在請求正文中以 JSON 格式提供新對象。 你還應(yīng)添加一個請求標(biāo)頭指定 Content-Type 為 application/json。

顯示 POST 和響應(yīng)的 Postman 控制臺

該方法返回在響應(yīng)中新建的項。

更新項目

通過使用 HTTP PUT 請求來修改記錄。 除了此更改之外,Edit 方法幾乎與 Create 完全相同。 請注意,如果未找到記錄,則 Edit 操作將返回 NotFound(404) 響應(yīng)。

C#

[HttpPut]
public IActionResult Edit([FromBody] ToDoItem item)
{
    try
    {
        if (item == null || !ModelState.IsValid)
        {
            return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
        }
        var existingItem = _toDoRepository.Find(item.ID);
        if (existingItem == null)
        {
            return NotFound(ErrorCode.RecordNotFound.ToString());
        }
        _toDoRepository.Update(item);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotUpdateItem.ToString());
    }
    return NoContent();
}

若要使用 Postman 進(jìn)行測試,將謂詞更改為 PUT。 在請求正文中指定要更新的對象數(shù)據(jù)。

顯示 PUT 和響應(yīng)的 Postman 控制臺

為了與預(yù)先存在的 API 保持一致,此方法在成功時返回 NoContent (204) 響應(yīng)。

刪除項目

刪除記錄可以通過向服務(wù)發(fā)出 DELETE 請求并傳遞要刪除項的 ID 來完成。 與更新一樣,請求的項不存在時會收到 NotFound 響應(yīng)。 請求成功會得到 NoContent (204) 響應(yīng)。

C#

[HttpDelete("{id}")]
public IActionResult Delete(string id)
{
    try
    {
        var item = _toDoRepository.Find(id);
        if (item == null)
        {
            return NotFound(ErrorCode.RecordNotFound.ToString());
        }
        _toDoRepository.Delete(id);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotDeleteItem.ToString());
    }
    return NoContent();
}

請注意,在測試刪除功能時,請求正文中不需要任何內(nèi)容。

顯示 DELETE 和響應(yīng)的 Postman 控制臺

常見的 Web API 約定

開發(fā)應(yīng)用程序的后端服務(wù)時,你將想要使用一組一致的約定或策略來處理橫切關(guān)注點。 例如,在上面所示服務(wù)中,針對不存在的特定記錄的請求會收到 NotFound 響應(yīng),而不是BadRequest 響應(yīng)。 同樣,對于此服務(wù),傳遞模型綁定類型的命令始終檢查 ModelState.IsValid 并為無效的模型類型返回 BadRequest。

一旦為 Api 指定通用策略,一般可以將其封裝在 Filter(篩選器)。 詳細(xì)了解 如何封裝 ASP.NET Core MVC 應(yīng)用程序中的通用 API 策略。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號