[ASP.NET] WebAPI Multiple Parameters Design

  • 5100
  • 0

[ASP.NET] WebAPI Multiple Parameters Design

在Web API設計上有時我們不見得傳遞一個參數就能滿足需求,在前面二篇文章中(WebAPI Post Mapping 複雜型別 & WebAPI Get 使用複雜型別) 我們也談及到如何使用複雜型別來做為參數的傳遞,這時就能滿足我們有多參數的需求,然而有時候這些參數並不是相互有關聯性,只是因為某些因素不得不要求呼叫端在每次呼叫時傳送必須給予,那麼設計上我們該如何切割呢?

假設情境:呼叫Web API建立一筆員工基本資料

我們會建立一個Web API並傳遞具有一個Employee類別的參數,大致會像下面程式碼這樣

[HttpPost]
public void AddEmployee(Employee empobj)
{
   //Do Add Employee 
}

Employee類別

public class Employee
{
    public String EmpNo { get; set; }
    public String Name { get; set; }
    public Employee()
    {
        //
        // TODO: 在這裡新增建構函式邏輯
        //
    }
}

 

接著假設我們因為要記錄呼叫端是來自於什麼設備的呼叫,所以我們會想要記錄設備的一些資訊( 名稱、作業系統、使用語系 ),並且在希望在每次呼叫時都能取得,所以我們建立一個DeviceInfo類別

public class DeviceInfo
{
    public String Name { get; set; }
    public String OsVersion { get; set; }
    public String Lang { get; set; }
    public DeviceInfo()
    {
        //
        // TODO: 在這裡新增建構函式邏輯
        //
    }
}

 

然後直覺上會為Web API加入這個類別參數,形成一個具有二個複雜型別參數的Web API

// POST api/<controller>
[HttpPost]
public void AddEmployee(Employee empobj,DeviceInfo devobj)
{
    //Do Add Employee 
}

 

但很快的您會發現這樣具有二個複雜型別參數的Web API是不能運作的,原因是當傳遞複雜型別時是由請求的message body內容來取得,並由 .Net Framework自動幫我們做了Mapping,而且只支援一個參數。所以接著我們把原本Employee類別納入DeviceInfo類別做為其屬性,就會變成如下

public class Employee
{
    public String EmpNo { get; set; }
    public String Name { get; set; }
    public DeviceInfo DevInfo { get; set; } 
    public Employee()
    {
        //
        // TODO: 在這裡新增建構函式邏輯
        //
    }
}

這樣Web API就可以維持原本的方式透傳遞Employee類別做為唯一的參數,並可以正常呼叫。

但是 這樣一來Employee類別裡夾帶了原本與Employee無關的屬性並不是一件好事,此外並非每個使用到Employee類別的AP都有記錄呼叫端資訊的需求,這會使得Employee類別變的有些怪異,因此筆者的做法會是多加一層做為Web API專用參數類別,而這個專用參數類別的內容則依需求來組合,以這個例子來說,筆者會建立一個AddEmpWebApiParameter類別做為專用參數類別

public class AddEmpWebApiParameter
{
    public Employee EmpObj { get; set; }
    public DeviceInfo DevInfo { get; set; }
    public AddEmpWebApiParameter()
    {
        //
        // TODO: 在這裡新增建構函式邏輯
        //
    }
}

而在Web API的部份則調整為

// POST api/<controller>
[HttpPost]
public void AddEmployee(AddEmpWebApiParameter para)
{
    Employee emp = para.EmpObj;
    DeviceInfo devinfo = para.DevInfo;
    //Do Add Employee 
}

 

在概念上就是每個類別裡只具有跟自已有關的成員,不去過問外界的使用情境,而外界的需求則以組合的概念來完成,上面的演示過程簡單說明這樣的一個概念,當然在實務上設計還會搭配介面及分層設計來進行,希望這個說明對大家在設計Web API有所幫助,也歡迎有任何建議可以相互討論。

Ref :

http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

 

若本文對您有所幫助,歡迎轉貼,但請在加註【轉貼】及來源出處,並在附上本篇的超連結,感恩您的配合囉。

By No.18