使用WebApiClient請求和管理Restful Api


前言

本篇文章的內容是WebApiClient應用說明篇,如果你沒有了解過WebApiClient,可以先閱讀以下相關文章:

背景

隨着Wcf、Webservice等的SOAP的份額越來越少,以及Restful Api的興起,目前幾乎所有新平台提供的接口,都只提供Restful Api,而.net平台下,沒有類似Wcf這么簡單的客戶端可以直接請求和管理這些Restful api的解決方案,.net平台提供的HttpWebRequest、WebClient和HttpClient這三個類庫,可用於實現Http接口的請求,但相比wcf得益於soap自我描述實現的自動生成客戶端調用代碼,Restful就沒這么方便了,無論使用HttpWebRequest還是HttpClient,都需要對每個Api縮寫沉長的調用代碼。

使用WebApiClient

WebApiClient是在這樣的背景下產生一款Http全異步的客戶端庫,它的出現,大幅度減輕了接口調用者的工作量,而且在調用Http接口上還非常容易維護和更新,還可以輕松應對設計不太友好的一些http接口。

使用WebApiClient,編程人員不再需要手動實現路徑拼接、參數拼接、請求體組裝和響應映射為模型這些繁瑣的過程,以下為WebApiClient應用到項目中的一般流程:

1 聲明http接口的Interface

[JsonReturn]
public interface IIotRemotePush : IDisposable
{
    /// <summary>
    /// 創建遠程推送賬號
    /// </summary>
    /// <param name="auth">授權</param>
    /// <returns></returns>
    [HttpPost("/v1/RemotePush/CreateAccount")]
    ITask<ApiResult<PushAccount>> CreateAccountAsync(IotBasicAuth auth);

    /// <summary>
    /// 獲取推送服務信息
    /// </summary>
    /// <param name="id">pushId</param>
    /// <returns></returns>
    [HttpGet("/v1/Mqtt/GetPushSevice?id={id}")]
    ITask<ApiResult<MqttService>> GetPushSeviceAsync(string id);
}

/// <summary>
/// Api結果接口
/// </summary>
public interface IApiResult
{
    /// <summary>
    /// 錯誤碼
    /// </summary>      
    ErrorCode Code { get; set; }

    /// <summary>
    /// 相關提示信息
    /// </summary>
    string Msg { get; set; }
}


/// <summary>
/// 表示Api結果
/// </summary>
public class ApiResult<T> : IApiResult
{
    /// <summary>
    /// 錯誤碼
    /// </summary>
    public ErrorCode Code { get; set; }

    /// <summary>
    /// 相關提示信息
    /// </summary>
    public string Msg { get; set; }

    /// <summary>
    /// 業務數據
    /// </summary>
    public T Data { get; set; }
}

2 調用http接口

WebApiClient不需要開者實現接口,使用HttpApiClient.Create方法可以動態創建接口的實現類的實例,調用實例的方法,就完成一個Api的請求。

using (var iotApi = HttpApiClient.Create<IIotRemotePush>())
{
    var auth = new IotBasicAuth(config.AppId, config.AppToken);
    var createResult = await iotApi.CreateAccountAsync(auth);
    if (createResult.Code != ErrorCode.NoError)
    {
        return null;
    }

    config.PushId = createResult.Data.Id;
    config.PushToken = createResult.Data.Token;
    await db.SaveChangesAsync();

    return config;
}

3 異常定義與異常處理

在以上接口中,接口返回的都是ApiResult 類型,此類型定義了一個ErrorCode類型的Code字段,這是業務的錯誤碼,我們可以把它轉換為.net的異常來處理。

/// <summary>
/// 表示Iot異常
/// </summary>
public class IotException : Exception
{
    /// <summary>
    /// 錯誤碼
    /// </summary>
    public ErrorCode ErrorCode { get; private set; }

    /// <summary>
    /// Iot異常
    /// </summary>
    /// <param name="apiResult">api結果值</param>
    public IotException(IApiResult apiResult)
        : base(apiResult.Msg)
    {
        this.ErrorCode = apiResult.Code;
    }
}

我們還應該在Interface上擴展JsonResult,用於將ApiResult的ErrorCode轉換為IotException,並拋出:

/// <summary>
/// 表示IotJson結果
/// </summary>
public class IotJsonResultAttribute : JsonReturnAttribute
{
    protected override async Task<object> GetTaskResult(ApiActionContext context)
    {
        var apiResult = await base.GetTaskResult(context) as IApiResult;
        if (apiResult != null && apiResult.Code != ErrorCode.NoError)
        {
            throw new IotException(apiResult);
        }
        return apiResult;
    }
}

然后將新的IotJsonResultAttribute在Interface上替換JsonReturnAttribute:

[IotJsonResult]
public interface IIotRemotePush : IDisposable
{
   ...
}

最后,調用http接口的時候,可以使用Handle()擴展方法處理異常:

using (var iotApi = HttpApiClient.Create<IIotRemotePush>())
{
    var auth = new IotBasicAuth(config.AppId, config.AppToken);
    var createResult = await iotApi.CreateAccountAsync(auth)
        .Handle()
        .WhenCatch<IotException>(ex =>
        {
            // process exception
            return default(ApiResult<PushAccount>);
        })
        .WhenCatch<Exception>(ex =>
        {
            // process exception
            return default(ApiResult<PushAccount>);
        });

    if (createResult == null)
    {
        return null;
    }

    config.PushId = createResult.Data.Id;
    config.PushToken = createResult.Data.Token;
    await db.SaveChangesAsync();

    return config;
}

WebApiClient現狀

WebApiClient項目目前已加入.NET China Foundation,正在為.net開源作出自己的一點貢獻。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM