ASP.NET Core開発に関する一連の記事の第2部を紹介します。 このチュートリアルでは、ASP.NET Core MVCを使用してモバイルアプリケーションをサポートするサーバーサービスを作成する方法を学習します。
ASP.NET Coreに関する2番目のシリーズの記事
- モバイルアプリケーション用のサーバーサービスの作成。
- dotnet watchを使用してASP.NET Coreアプリケーションを開発します 。
- Swaggerを使用したASP.NET Web APIリファレンスページの作成
- .NET(OWIN)のWebインターフェイスを開きます。
- サーバー上の適切な.NET開発環境の選択。
記事の最初のシリーズはここにあります 。
サンプルモバイルアプリケーション
モバイルアプリケーションは、ASP.NET Coreサーバーサービスと簡単に通信できます。 ここでは、サンプルのサーバーサービスコードをダウンロードできます。
この資料では、 Xamarin Forms ToDoRestアプリケーションをクライアントとして使用します。 Android、iOS、Windows用のデバイス用の個別のクライアントが含まれています。 上記のリンクを使用して、アプリケーションの作成(および必要な無料のXamarinツールのインストール)に役立つガイドを見つけてください。また、サンプルのXamarinソリューションをダウンロードすることもできます。 これには、2つのASP.NET Web APIサービスのプロジェクトが含まれており、この記事のASP.NET Coreアプリケーションに置き換えられています(クライアント側からの変更は不要です)。
機能
ToDoRestアプリケーションは、To-Doアイテムのリスト、追加、削除、および更新をサポートしています。 各要素には、その要素が完成したかどうかを示す識別子、名前、メモ、プロパティが付与されます。
上記のように、要素のメインビューには各要素の名前があり、フラグの存在はそれが完了したかどうかを示します。
[+]アイコンをタップして、アイテムを追加するためのダイアログボックスを開きます。
メインリストのアイテムをタップして、名前、メモ、実行ステータスを編集するためのダイアログボックスを開くか、アイテムを削除します。
このサンプルは、デフォルトで、 developer.xamarin.comにあるサービスを使用し、読み取り専用を許可します。 次のセクションで作成され、コンピューターで動作するASP.NET Coreアプリケーションで個別にテストするには、 RestUrl
定数を更新する必要があります。 ToDoREST
プロジェクトに移動して、 Constants.csファイルを開きます。 RestUrl
をコンピューターのIPアドレスに置き換えます(アドレスはPCではなくデバイスエミュレーターから使用されるため、localhostまたは127.0.0.1であってはなりません)。 ポート番号(5000)も追加します。 デバイスでサービスを機能させるには、このポートへのアクセスをブロックするファイアウォールをオフにすることを忘れないでください。
// 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}";
ASP.NET Coreプロジェクトの作成
Visual Studioで新しいASP.NET Core Webアプリケーションを作成します。 Web APIテンプレートを選択し、認証を無効にします。 プロジェクトにToDoApiという名前を付けます。
アプリケーションは、ポート5000へのすべての要求に応答する必要があります.UseUrls("http://*:5000")
に追加して、次の結果を取得します。
var host = new WebHostBuilder() .UseKestrel() .UseUrls("http://*:5000") .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build();
注:IIS Expressではなく、アプリケーションを直接実行するようにしてください。IISExpressは、デフォルトでは非ローカルリクエストを無視します。 コマンドラインからdotnet run
か、Visual Studioツールバーの[デバッグターゲット]ドロップダウンメニューからアプリケーション名を選択します。
To Do要素を表すモデルクラスを追加します。 [Required]
属性で[Required]
フィールドをマークします。
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メソッドには、データを処理する方法が必要です。 Xamarinサンプルと同じIToDoRepository
インターフェイスを使用します。
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); } }
この例では、実装は要素のプライベートコレクションを使用します。
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で実装を構成します 。
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); services.AddSingleton<IToDoRepository,ToDoRepository>(); }
これで、 ToDoItemsControllerの作成に進むことができます。
Web APIの作成の詳細については、記事「ASP.NET Core MVCおよびVisual Studioを使用した最初のWeb APIの作成」を参照してください。
コントローラーの作成
新しいToDoItemsControllerをプロジェクトに追加します。 Microsoft.AspNetCore.Mvc.Controllerからプロパティを継承する必要があります。 Route
属性を追加して、コントローラーがパスに対して実行され、 api/todoitems
始まるリクエストを処理することを示します。 ルート内のトークン[controller]
は、 [controller]
の名前に置き換えられます(接尾部コントローラーなし)。 これは特にグローバルルートに役立ちます。 ルーティングの詳細。
コントローラーが機能するには、 IToDoRepository;
パラメーターがIToDoRepository;
コントローラーコンストラクターを介してこのタイプのインスタンスを要求します。 実行時に、 依存性注入のプラットフォームサポートのおかげで、このインスタンスが提供されます。
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は、データソースでの作成、読み取り、更新、削除(CRUD)操作のための4つのHTTPコマンドをサポートしています。 最も単純な操作は、HTTP Get要求に対応する読み取りです。
読書アイテム
アイテムのリストを要求するには、 List
メソッドでGET要求を実行します。 List
メソッドの[HttpGet]
属性は、このアクションがGET要求のみを処理することを示しています。 このアクションのルートは、コントローラーに示されているルートです。 ルートの一部としてアクションの名前を使用する必要はありません。 各アクションに一意で明確なルートがあることを確認する必要があります。 特定のルートを作成するための属性ルーティングは、コントローラーとメソッドの両方のレベルで適用できます。
[HttpGet] public IActionResult List() { return Ok(_toDoRepository.All); }
List
メソッドList
、200 OK応答コードと、JSONとしてシリアル化されたすべてのToDo要素のリストをList
ます。
以下に示すように、 Postmanなどのいくつかのツールを使用して、新しいAPIメソッドをテストできます。
アイテムを作成する
慣例により、新しいデータ項目の作成はHTTP POSTコマンドにマッピングされます。 [HttpPost];
属性はCreate
メソッドに適用されCreate
[HttpPost];
さらに、このメソッドはIDパラメーターとToDoItem
インスタンスをToDoItem
ます。 [HttpPost]
などのコマンド属性は、ルート文字列(この例では{id}
)を取ることができます。 結果は、アクションに[Route]
属性を追加した場合と同じになります。 item
引数はPOST本文で渡されるため、このパラメーターは[FromBody]
属性で装飾されています。
メソッド内で、要素が正しく構成されているかどうか、および以前にデータウェアハウスに存在していたかどうかがチェックされます。 エラーがない場合は、リポジトリを使用して追加されます。 ModelState.IsValid
はモデル検証を実行します。 これは、ユーザー入力を受け付けるすべてのAPIメソッドで実行する必要があります。
[HttpPost("{id}")] public IActionResult Create(string id, [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); }
サンプルでは、モバイルクライアントに送信されるエラーコードの列挙を使用します。
public enum ErrorCode { TodoItemNameAndNotesRequired, TodoItemIDInUse, RecordNotFound, CouldNotCreateItem, CouldNotUpdateItem, CouldNotDeleteItem }
新しい要素の追加をテストするには、Postmanを使用します。POSTコマンドを選択します。これにより、リクエスト本文にJSON形式の新しいオブジェクトが提供されます。 また、 application/json
Content-Type
を示すリクエストヘッダーを追加しapplication/json
。
応答では、メソッドは新しく作成された要素を返します。
アイテムを更新
レコードは、HTTP PUT要求を使用して変更できます。 また、 Edit
メソッドはCreate
とほぼ同じです。 レコードが見つからない場合、 Edit
アクションはNotFound
応答(404)を返すことにNotFound
てください。
[HttpPut("{id}")] public IActionResult Edit(string id, [FromBody] ToDoItem item) { try { if (item == null || !ModelState.IsValid) { return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString()); } var existingItem = _toDoRepository.Find(id); if (existingItem == null) { return NotFound(ErrorCode.RecordNotFound.ToString()); } _toDoRepository.Update(item); } catch (Exception) { return BadRequest(ErrorCode.CouldNotUpdateItem.ToString()); } return NoContent(); }
Postmanをテストするには、コマンドをPUTに変更し、更新されたレコードのIDをURLに追加します。 リクエスト本文に更新されたオブジェクトのデータを指定します。
成功した場合、メソッドNoContent
(204)応答をNoContent
、既存のAPIとの一貫性を確保します。
アイテムを削除する
レコードを削除するには、サービスに対してDELETEリクエストを行い、削除するアイテムのIDを渡す必要があります。 これらの更新後、存在しない要素に対する要求はNotFound
応答を受け取り、成功した要求はNotFound
応答を受け取ります(204)。
[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(); }
削除機能をテストする場合、リクエスト本文に何も追加する必要がないことに注意してください。
一般的なWeb APIの規則
アプリケーションのサーバーサービスを開発する場合、一連の論理的な合意またはポリシーを作成して、新たな問題を解決することをお勧めします。 たとえば、上記のサービスでは、見つからなかった特定のレコードの要求は、 NotFound
ではなくBadRequest
応答をNotFound
BadRequest
。 同様に、このサービスに発行され、モデルタイプに渡されたコマンドは、常にModelState.IsValid
をチェックし、無効なモデルタイプに対してBadRequest
を発行しBadRequest
。
APIの一般的なポリシーを定義するときに、フィルターをカプセル化できます。 この記事では、ASP.NET Core MVCアプリケーションで一般的なAPIポリシーをカプセル化する方法を学習できます。