使用HttpClient呼叫Web API – 2

by vivid 18. 十月 2017 17:30

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N171018802
出刊日期: 2017/10/18

在這篇文章中,將延續《使用HttpClient呼叫Web API - 1》一文的情境,介紹如何在ASP.NET Core MVC的控制器之中,利用「HttpClent」類別來呼叫ASP.NET Core MVC 2.0專案中建立的Web API。

 

設計ASP.NET Core MVC控制器

從「Solution Explorer」視窗- 「Controllers」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Scaffolded Item」,或「Controller」項目,在「Add Scaffold」對話盒中選取「MVC」-「Controller」分類下的「MVC Controller - Empty」項目,然後按下「Add 」按鈕,請參考下圖所示:

clip_image002

圖 1:加入MVC控制器。

在「Add Controller」對話盒中,設定控制器名稱為「HomeController」;然後按下「Add 」按鈕,請參考下圖所示:

clip_image004

圖 2:加入HomeController控制器。

ASP.NET Web API提供一組新的用戶端應用程式開發介面,以叫用HTTP服務,相關的類別都在「System.Net.Http」命名空間下,透過此命名空間下的「HttpClient」類別來傳送HTTP請求與回應。「HttpClient」類別支援Task可以非同步開發模型來叫用服務。

預設「HomeController」類別中會自動加入以下程式碼,其中包含一個「Index」方法,修改「Index」方法,建立「HttpClient」物件,設定「BaseAddress」屬性,指定為ASP.NET Web API所在網址,然後叫用「GetAsync」方法,以非同步方式取得服務執行的結果後,叫用「HttpContent」類別「ReadAsStringAsync」方法,從回傳的Task物件之「Result」屬性取得執行結果:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Net.Http.Headers;
using WebAPIDemo.Models;
using Newtonsoft.Json;

namespace WebAPIDemo.Controllers {
  public class HomeController : Controller {
    public IActionResult Index( ) {
      using ( HttpClient client = new HttpClient( ) ) {
        client.BaseAddress = new Uri( "http://localhost:1880" );
        HttpResponseMessage response = client.GetAsync( "/api/course" ).Result;
        string result = response.Content.ReadAsStringAsync( ).Result;
        List<Course> data = JsonConvert.DeserializeObject<List<Course>>( result );
        return View( data );
      }
    }
  }
}

設計檢視

從「Solution Explorer」視窗 - 專案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Folder」選項,將新建立的資料夾命名為「Views」。在「Views」資料夾加一個「_ViewImports.cshtml」檔案。從「Solution Explorer」視窗專案名稱下「Views」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」選項,選取Web分類中的「MVC View Imports Page」,檔案名稱設定為「_ViewImports.cshtml」,然後按下「Add」按鈕:

clip_image006

圖 3:加入_ViewImports.cshtml。

修改「_ViewImports.cshtml」檔案,在其中加入以下程式碼,@addTagHelper第一個參數指定要載入的Tag Helpers,「*」號代表所有的Tag Helpers。第二個參數指定包含Tag Helpers的組件名稱。內建的ASP.NET Core Tag Helpers放在Microsoft.AspNetCore.Mvc.TagHelpers組件之中:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

建立「Index」檢視。將游標停留在「HomeController」控制器程式設計畫面「Index」方法之中,按滑鼠右鍵,從快捷選單選取「Add View」,請參考下圖所示。(若沒有看見「Add View」選單,請將「HomeController.cs」程式設計畫面關閉再重開,或關閉Visual Studio開發工具之後,再重新開啟):

clip_image008

圖 4:加入「Index」檢視。

在「Add View」對話盒中,設定:

· View name:「Index」。

· Template:從右方的下拉式清單方塊選取「List」項目。

· Model class:從右方的下拉式清單方塊選取「Course」項目。

· 清除勾選所有核取方塊。

然後按下「Add」按鈕。Visual Studio 2017便會在「Views\Home」資料夾下,新增一個「Index.cshtml」檔案,請參考下圖所示:

clip_image010

圖 5:加入Index檢視。

修改產生的Index檢視下方三行叫用Html.ActionLink方法產生超連結的程式碼,內容如下:

@model IEnumerable<WebAPIDemo.Models.Course>
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title> Index </title>
</head>
<body>
  <p>
    <a asp-action="Create"> Create New </a>
  </p>
  <table class="table">
    <thead>
      <tr>
        <th>
          @Html.DisplayNameFor( model => model.Id )
        </th>
        <th>
          @Html.DisplayNameFor( model => model.Name )
        </th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      @foreach ( var item in Model ) {
        <tr>
          <td>
            @Html.DisplayFor( modelItem => item.Id )
          </td>
          <td>
            @Html.DisplayFor( modelItem => item.Name )
          </td>
          <td>
            @Html.ActionLink( "Edit" , "Edit" , new { id = item.Id } ) |
            @Html.ActionLink( "Details" , "Details" , new { id = item.Id } ) |
            @Html.ActionLink( "Delete" , "Delete" , new { id = item.Id } )
          </td>
        </tr>
      }
    </tbody>
  </table>
</body>
</html>

 

修改「Startup」類別,在「Configure」方法叫用「UseMvcWithDefaultRoute」方法設定預設的MVC路由:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace WebAPIDemo {
  public class Startup {
    public Startup( IConfiguration configuration ) {
      Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices( IServiceCollection services ) {
      services.AddMvc( );
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure( IApplicationBuilder app , IHostingEnvironment env ) {
      if ( env.IsDevelopment( ) ) {
        app.UseDeveloperExceptionPage( );
      }
      app.UseMvcWithDefaultRoute( );
    }
  }
}


 

選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:1880/home/

執行結果參考如下:

clip_image012

圖 6:叫用Web API查詢資料。

結束執行程式,回到Visual Studio 開發工具程式編輯畫面。

新增資料

在「CourseController」類別中加入兩個「Create」方法,第一個「Create」方法沒有參數;第二個「Create」方法接收一個「Course」型別的參數,方法上方標識「HttpPost」Attribute。在標識「HttpPost」 Attribute的「Create」方法中,從course參數取得檢視傳送至控制器的Course資料,利用「JsonConvert.SerializeObject」方法將物件序列化為JSON字串,然後叫用「HttpClient」物件的「PostAsync」方法透過Web API新增資料。

public IActionResult Create( ) {
  return View( );
}

[HttpPost]
public IActionResult Create( Course course ) {
  using ( HttpClient client = new HttpClient( ) ) {
    client.BaseAddress = new Uri( "http://localhost:1880" );
    string stringData = JsonConvert.SerializeObject( course );
    var data = new StringContent( stringData , System.Text.Encoding.UTF8 , "application/json" );
    HttpResponseMessage response = client.PostAsync( "/api/course" , data ).Result;
    //var r = response.Content.ReadAsStringAsync( ).Result;
    return RedirectToAction( "Index" );
  }
}

 

建立「Create」檢視。將游標停留在控制器程式設計畫面「Create」方法之中,按滑鼠右鍵,從快捷選單選取「Add View」。在「Add View」對話盒中,設定:

· View name:「Create」。

· Template:從右方的下拉式清單方塊選取「Delete」項目。

· Model class:從右方的下拉式清單方塊選取「Course」項目。

· 清除勾選所有核取方塊。

clip_image014

圖 7:建立「Create」檢視。

然後按下「Add」按鈕。Visual Studio 2017便會在「Views\Home」資料夾下,新增一個「Create.cshtml 」 檔案,包含以下程式碼:

 

@model WebAPIDemo.Models.Course
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title> Create </title>
</head>
<body>
  <h4> Course </h4>
  <hr />
  <div class="row">
    <div class="col-md-4">
      <form asp-action="Create">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
          <label asp-for="Id" class="control-label"> </label>
          <input asp-for="Id" class="form-control" />
          <span asp-validation-for="Id" class="text-danger"> </span>
        </div>
        <div class="form-group">
          <label asp-for="Name" class="control-label"> </label>
          <input asp-for="Name" class="form-control" />
          <span asp-validation-for="Name" class="text-danger"> </span>
        </div>
        <div class="form-group">
          <input type="submit" value="Create" class="btn btn-default" />
        </div>
      </form>
    </div>
  </div>
  <div>
    <a asp-action="Index"> Back to List </a>
  </div>
</body>
</html>

選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:1880/home/

執行結果參考如下:

clip_image016

圖 8:點選「Create New」新增資料。

輸入一筆新資料,然後按下「Create」按鈕:

clip_image018

圖 9:輸入要新增的資料。

新增成功將回到清單頁,並顯示最新的清單資料:

clip_image020

圖 10:顯示最新的清單資料。

結束執行程式,回到Visual Studio 開發工具程式編輯畫面。

 

修改資料

在「HomeController」類別中加入兩個「Edit」方法程式碼,第一個「Edit」方法接收一個「string」型別的「id」參數;第二個「Edit」方法接收一個「Course」型別的「course」參數:

public IActionResult Edit( string id ) {
  using ( HttpClient client = new HttpClient( ) ) {
    client.BaseAddress = new Uri( "http://localhost:1880" );
    HttpResponseMessage response = client.GetAsync( $"/api/course/{id}" ).Result;
    string data = response.Content.ReadAsStringAsync( ).Result;
    Course course = JsonConvert.DeserializeObject<Course>( data );
    return View( course );
  }
}
[HttpPost]
public IActionResult Edit( Course course ) {
  using ( HttpClient client = new HttpClient( ) ) {
    client.BaseAddress = new Uri( "http://localhost:1880" );
    string data = JsonConvert.SerializeObject( course );
    var content = new StringContent( data, System.Text.Encoding.UTF8 , "application/json" );
    HttpResponseMessage response = client.PutAsync( $"/api/course/{course.Id}" , content ).Result;
    return RedirectToAction( "Index" );
  }
}

 

在標識「HttpPost」Attribute的「Edit」方法中,叫用「HttpClient」的「PutAsync」方法將JSON字串傳送到Web API做修改,然後利用「RedirectToAction」方法回到「Index」檢視。

建立「Edit」檢視。將游標停留在「HomeController」控制器程式設計畫面「Edit」方法之中,按滑鼠右鍵,從快捷選單選取「Add View」項目。在「Add View」對話盒中,設定:

· View name:「Edit」。

· Template:從右方的下拉式清單方塊選取「Edit」項目。

· Model class:從右方的下拉式清單方塊選取「Course」項目。

· 清除勾選所有核取方塊。

clip_image022

圖 11:建立「Edit」檢視。

然後按下「Add」按鈕。Visual Studio 2017便會在「Views\Home」資料夾下,新增一個「Edit.cshtml」檔案。目前Edit檢視的程式碼看起來如下:

@model WebAPIDemo.Models.Course
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title> Edit </title>
</head>
<body>
  <h4> Course </h4>
  <hr />
  <div class="row">
    <div class="col-md-4">
      <form asp-action="Edit">
        <div asp-validation-summary="ModelOnly" class="text-danger"> </div>
        <div class="form-group">
          <label asp-for="Id" class="control-label"> </label>
          <input asp-for="Id" class="form-control" />
          <span asp-validation-for="Id" class="text-danger"> </span>
        </div>
        <div class="form-group">
          <label asp-for="Name" class="control-label"> </label>
          <input asp-for="Name" class="form-control" />
          <span asp-validation-for="Name" class="text-danger"> </span>
        </div>
        <div class="form-group">
          <input type="submit" value="Save" class="btn btn-default" />
        </div>
      </form>
    </div>
  </div>
  <div>
    <a asp-action="Index"> Back to List </a>
  </div>
</body>
</html>

 

選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:1880/home/

執行結果參考如下,點選想要修改的課程資料:

clip_image024

圖 12:點選想要修改的課程資料。

進入資料編輯畫面修改資料,然後按下「Save」按鈕:

clip_image026

圖 13:修改資料。

儲存成功後將回到清單頁,並顯示修改過的最新清單資料:

clip_image028

圖 14:顯示修改過的最新清單資料。

結束執行程式,回到Visual Studio 開發工具程式編輯畫面。

 

刪除資料

在「HomeController」類別中加入「Delete」方法與「DeleteConfirm」方法。由於這兩個方法的參數都是一個「int」型別的「id」變數,因此方法名稱不能命名為相同,不符合程式語言方法多載(Method Overload)的原則。解決方式是將兩個方法分別取不同名稱:Delete與DeleteConfirm,並在DeleteConfirm方法上方套用ActionName("Delete") Attribute表示這是資料使用HTTP POST提交時,要執行的「Delete」方法。

public IActionResult Delete( int id ) {
  using ( HttpClient client = new HttpClient( ) ) {
    client.BaseAddress = new Uri( "http://localhost:1880" );
    HttpResponseMessage response = client.GetAsync( $"/api/course/{id}" ).Result;
    string data = response.Content.ReadAsStringAsync( ).Result;
    Course course = JsonConvert.DeserializeObject<Course>( data );
    return View( course );
  }
}

[HttpPost, ActionName( "Delete" )]
public IActionResult DeleteConfirm( int id ) {
  using ( HttpClient client = new HttpClient( ) ) {
    client.BaseAddress = new Uri( "http://localhost:1880" );
    HttpResponseMessage response = client.DeleteAsync( $"/api/course/{id}" ).Result;
    return RedirectToAction( "Index" );
  }
}

 

建立「Delete」檢視。將游標停留在控制器程式設計畫面「Delete」方法之中,按滑鼠右鍵,從快捷選單選取「Add View」,在「Add View」對話盒中,設定:

· View name:「Edit」。

· Template:從右方的下拉式清單方塊選取「Edit」項目。

· Model class:從右方的下拉式清單方塊選取「Course」項目。

· 清除勾選所有核取方塊。

clip_image030

圖 15:建立「Delete」檢視。

然後按下「Add」按鈕。Visual Studio 2017便會在「Views\Home」資料夾下,新增一個「Delete.cshtml」檔案。目前Delete檢視的程式碼看起來如下:

@model WebAPIDemo.Models.Course
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title> Delete </title>
</head>
<body>
  <h3> Are you sure you want to delete this? </h3>
  <div>
    <h4> Course </h4>
    <hr />
    <dl class="dl-horizontal">
      <dt>
        @Html.DisplayNameFor( model => model.Id )
      </dt>
      <dd>
        @Html.DisplayFor( model => model.Id )
      </dd>
      <dt>
        @Html.DisplayNameFor( model => model.Name )
      </dt>
      <dd>
        @Html.DisplayFor( model => model.Name )
      </dd>
    </dl>

    <form asp-action="Delete">
      <input type="submit" value="Delete" class="btn btn-default" /> |
      <a asp-action="Index"> Back to List </a>
    </form>
  </div>
</body>
</html>

 

選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:1880/home/

執行結果參考如下,點選想要刪除的課程資料:

clip_image032

圖 16:點選想要刪除的課程資料。

進入確認刪除頁,若按下「Delete」按鈕則將資料刪除,並回到清單頁顯示最新的課程資料:

clip_image034

圖 17:確認刪除。

結束執行程式,回到Visual Studio 開發工具程式編輯畫面。

Tags:

.NET Core | ASP.NET Core MVC | .NET Magazine國際中文電子雜誌 | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List