經過前兩天關於本次系統架構的簡單介紹之後,我們將要開始建立我們的Api系統,今天主要的內容將會向大家簡單介紹Api的各個Layer大概會如何規劃,以及程式碼架構會長什麼樣子,並且簡單的實現我們第一個Api。
今天的所有程式碼可以直接從Github上Get下來看喔!
ApiSample - Tag Day03
註: 若有跳出website專案無法載入,請先安裝typescript
※系統架構 - N Tier
為了讓程式碼更加容易擴充,並且增加可重複使用性,Api的主要系統架構採用N-Tier架構設計,而各Layer再依據不同的功能或是角色加以細分,以因應未來系統擴充或是提供給其它內部網站使用的可行性。
系統大致上可以概括為以下五個Layer
※Solution檔案結構
在準備建立的Solution資料夾下,建立屬於各Layer的資料夾,並且建立各Layer所擁有的專案
粉紅色為Layer資料夾,灰色為專案
建立完各Layer的資料夾,並且在各Layer的資料夾建立完專案之後,我們的Solution結構長的會像這樣
註: 網站部分使用Asp.Net MVC 4.0
※專案相依性
我們按照之前N Tier的關係圖,建立專案之間的參考,建立完成之後,透過Visual Studio的功能可以產生各專案之間的相依性圖形如下
※建立第一個Api
目標: 我們希望可以建立一個Api,使用者可以透過/Sample/Index,使用Get來取得Sample資料的清單
首先我們在ApiSample.Models專案,建立一個資料模型SampleModel.cs
public class SampleModel
{
public int Id { get; set; }
public string Data { get; set; }
public DateTime CreatedAt { get; set; }
}
接下來在ApiSample.DA.Interfaces專案建立Repository的介面ISampleRepository.cs
public interface ISampleRepository
{
IEnumerable GetSamples();
}
並在ApiSample.DA.Repository實現取得資料的部分SampleRepository.cs,這邊暫時使用假資料
public class SampleRepository : ISampleRepository
{
public IEnumerable GetSamples()
{
for (int i = 0; i < 10; i++)
{
yield return new SampleModel()
{
Id = i,
Data = string.Format("Data - {0}", i),
CreatedAt = DateTime.Now
};
}
}
}
實現BL層的介面與實作
ISampleService.cs
public interface ISampleService
{
IEnumerable GetSamples();
}
SampleService.cs
public class SampleService : ISampleService
{
public ISampleRepository SampleRepository { get; set; }
//// 尚未套用Ioc,暫時直接初始化
public SampleService()
: this(new SampleRepository())
{
}
public SampleService(ISampleRepository sampleRepository)
{
this.SampleRepository = sampleRepository;
}
public IEnumerable<SampleModel> GetSamples()
{
return this.SampleRepository.GetSamples();
}
}
在網站實現SampleController,在Index方法提供Sample資料清單
public class SampleController : Controller
{
public ISampleService SampleService { get; set; }
//// 尚未套用Ioc,暫時直接初始化
public SampleController()
:this(new SampleService())
{
}
public SampleController(ISampleService sampleService)
{
this.SampleService = sampleService;
}
public ActionResult Index()
{
var data = this.SampleService.GetSamples();
return Json(data, JsonRequestBehavior.AllowGet);
}
}
修改RouteConfig,讓起始畫面導至/Sample/Index
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Sample", action = "Index", id = UrlParameter.Optional }
);
}
}
按下F5執行網站,可以看到執行結果,得到Api的Json格式資料
※本日小結
在今天的介紹中,我們完成了第一個Api,也同時將我們的系統初步的架構了起來,接下來我們也將以此為基礎繼續實現我們Api所需要的各種功能,關於今天的內容歡迎大家一起討論^_^
Hi,大大您好,您的系列文對我幫助蠻大的!有幾個問題想請教您:
1.WebAPI應該是繼承ApiController,但您此篇範例依然是以一般的Controller來實做Demo,我請問的是WebAPI的Controller,您依然會是規劃在Website底下嗎?
2.如果系統有非常多的stored procedure,在Model的類別會如何規劃?抑或是直接在DA跟SP溝通,BL層做商業邏輯處理?如果SP參數一多,要怎樣規劃才比較好?
謝謝您,期待您後續文章=V=
HI,
關於你的第一個問題,我想應該是標題讓你誤會了,
雖然Asp.Net Web API可以讓我們非常快速的打造Restful Api,
但這系列文章主要還是以Asp.Net MVC為主,用Asp.Net MVC來打造透過Http的Api系統,
所以應該不會提到Asp.Net Web API的部分喔,不好意思^^"
不過Asp.NET MVC和Asp.Net Web API在系統架構上的使用應該都是大同小異的,
最主要的差別應該只是在Controller的部分,大部分的觀念都還是相通的,
所以幾乎所有提到的功能都同樣能使用Asp.Net WebAPI上實現,
可以視為Presentation Layer使用不同的技術來提供給使用者呼叫,
僅僅只有Controller的部分程式碼可能會不一樣而已。
而第二個問題,若DA是大量的Stored Procedure的話,
或許你也可以考慮使用Database First的Entity Framework會更方便,
我會選擇直接在DA跟Stored Procedure溝通,
如果有額外需要對Input或Output的資訊做其他商業邏輯處理才會放在BL (例如: 驗證、資料處理)
SP參數多的時候也可以考慮將所有參數定義為Model Class,
在DA層才處理Model對應到Stored Procedure的事情。
關於以上不知道有沒有回答到你的問題呢?
如果有疑問在麻煩你提出來囉 ^^"
Hi 大大您好,
若是DB限制直接存取Table的權限, 只允許使用SP與DB溝通.
在這樣的條件下, 還建議DA層使用EF與B溝通嗎?
Hi,
使用EF的好處是可以用強型別的物件與DB做溝通,
也可以避免掉一些直接撰寫SQL造成的typo,
雖然是透過SP操作DB,但也可以透過EF來讓使用DB更加方便,
如果擔心使用上會有甚麼問題的話可以嘗試先小部分的轉換去熟悉EF及確認導入的可行性,
評估之後,若使用EF可以幫助自己減少與DB操作的複雜度的話再大量導入。