顯示具有 ASP.NET MVC 標籤的文章。 顯示所有文章
顯示具有 ASP.NET MVC 標籤的文章。 顯示所有文章

2018年3月29日 星期四

使用 LinqPad 快速產生 Dapper 所需要的 SQL 語法 - Class、Insert、Update

前言

工作上目前已經很習慣用 Dapper 這種輕型的 ORM 來處理有關DAL層的應用,但相較於 Entity Freamwork,在處理新增/更新時就比較沒那麼方便,主要差異在Entity Freamwork 可以直接用物件操作的方式來做資料庫異動,而Dapper就必須寫SQL Commend,雖然有一些Open Source Extentions 已經封裝這些邏輯,譬如:SimpleCRUD﹉等,但實際使用常常得依規範設定一些屬性,有時發生錯誤時也不是那麼的直覺,故目前我還是會以SQL Commend為主。但產生Commend是一件麻煩事,如果搭配 Linqpad 寫一個Script 可以依需求快速產生所需要的commend,彈性是很大的,此篇文章介紹我在實務上我常用Scripts,來快速產生相關 SQL Commend

如何設定LinqPad

20180311_015834

Step 1 : 這邊可以直接瀏覽資料庫的Schema
Step 2 : 這邊使用C# Program 來撰寫我們要產生Script的程式
Step 3 : 選擇資料庫的連線字串

接著以下是我常用的Helper,只要貼到內容裡面即可產生


 

void Main()

{

 this.Connection

 .DumpClass(@"

SELECT * FROM Table

 ","ViewModelName")

 .Dump();

}

// Define other methods and classes here

public static class LINQPadExtensions

{

 private static readonly Dictionary TypeAliases = new Dictionary {

 { typeof(int), "int" },

 { typeof(short), "short" },

 { typeof(byte), "byte" },

 { typeof(byte[]), "byte[]" },

 { typeof(long), "long" },

 { typeof(double), "double" },

 { typeof(decimal), "decimal" },

 { typeof(float), "float" },

 { typeof(bool), "bool" },

 { typeof(string), "string" }

 };

 private static readonly HashSet NullableTypes = new HashSet {

 typeof(int),

 typeof(short),

 typeof(long),

 typeof(double),

 typeof(decimal),

 typeof(float),

 typeof(bool),

 typeof(DateTime)

 };

 public static string DumpClass(this IDbConnection connection, string sql,string Name)

 {

 if(connection.State != ConnectionState.Open)

 connection.Open();

 var cmd = connection.CreateCommand();

 cmd.CommandText = sql;

 var reader = cmd.ExecuteReader();

 var builder = new StringBuilder();

 do

 {

 if(reader.FieldCount <= 1) continue;

 builder.AppendLine("public class " + Name);

 builder.AppendLine("{");

 var schema = reader.GetSchemaTable();

 foreach (DataRow row in schema.Rows)

 {

 var type = (Type)row["DataType"];

 var name = TypeAliases.ContainsKey(type) ? TypeAliases[type] : type.Name;

 var isNullable = (bool)row["AllowDBNull"] && NullableTypes.Contains(type);

 var collumnName = (string)row["ColumnName"];

 builder.AppendLine(string.Format("\tpublic {0}{1} {2} {{ get; set; }}", name, isNullable ? "?" : string.Empty, collumnName));

 }

 builder.AppendLine("}");

 builder.AppendLine(); 

 } while(reader.NextResult());

 return builder.ToString();

 }

}


產生 Insert 語法



void Main()
{
 // SQL Command
 var sqlCommand = @"SELECT top 1 * FROM dbo.Table WITH (NOLOCK);";
 
 this.Connection.GenerateInsertCommand(sqlCommand.ToString(), "Table").Dump();
 
}
 
public static class LINQPadExtensions
{
 public static string GenerateInsertCommand(this IDbConnection connection, string sql, string tableName = "TableName")
 {
 if (connection.State != ConnectionState.Open)
 {
 connection.Open();
 }
 
 var cmd = connection.CreateCommand();
 cmd.CommandText = sql;
 var reader = cmd.ExecuteReader();
 
 var builder = new StringBuilder();
 do
 {
 if (reader.FieldCount <= 1)
 {
 continue;
 }
 
 builder.AppendFormat("INSERT INTO [dbo].[{0}]{1}", tableName, Environment.NewLine);
 builder.AppendLine("(");
 
 var schema = reader.GetSchemaTable();
 var columnNames = new List();
 
 foreach (DataRow row in schema.Rows)
 {
 var columnName = (string)row["ColumnName"];
 columnNames.Add(columnName);
 }
 
 foreach (var columnName in columnNames)
 {
 builder.AppendFormat(" [{0}]{1}{2}",
 columnName,
 columnNames.IndexOf(columnName).Equals(columnNames.Count - 1) ? "" : ",",
 Environment.NewLine);
 }
 
 builder.AppendLine(")");
 builder.AppendLine("VALUES");
 builder.AppendLine("(");
 
 foreach (var columnName in columnNames)
 {
 builder.AppendFormat(" @{0}{1}{2}",
 columnName,
 columnNames.IndexOf(columnName).Equals(columnNames.Count - 1) ? "" : ",",
 Environment.NewLine);
 }
 
 builder.AppendLine(");");
 builder.AppendLine();
 }
 while (reader.NextResult());
 
 return builder.ToString();
 }
}


產生 Update 語法


void Main()
{
 // SQL Command
 var tableName = "TableName";
 var sqlCommand = @"SELECT top 1 * FROM [dbo].["+tableName+"]";
 
 this.Connection.GenerateInsertCommand(sqlCommand.ToString(), tableName).Dump();
 
}
 
public static class LINQPadExtensions
{
 public static string GenerateInsertCommand(this IDbConnection connection, string sql, string tableName = "TableName")
 {
 if (connection.State != ConnectionState.Open)
 {
 connection.Open();
 }
 
 var cmd = connection.CreateCommand();
 cmd.CommandText = sql;
 var reader = cmd.ExecuteReader();
 
 var builder = new StringBuilder();
 do
 {
 if (reader.FieldCount <= 1)
 {
 continue;
 }
 
 builder.AppendFormat("UPDATE [dbo].[{0}] SET {1}", tableName, Environment.NewLine);
 // builder.AppendLine("(");
 
 var schema = reader.GetSchemaTable();
 var columnNames = new List();
 
 foreach (DataRow row in schema.Rows)
 {
 var columnName = (string)row["ColumnName"];
 columnNames.Add(columnName);
 }
 
 foreach (var columnName in columnNames)
 {
 builder.AppendFormat(" [{0}] = @{0}{1}{2}",
 columnName,
 columnNames.IndexOf(columnName).Equals(columnNames.Count - 1) ? "" : ",",
 Environment.NewLine);
 }
 
 builder.AppendLine("WHERE ID = @ID");
 }
 while (reader.NextResult());
 
 return builder.ToString();
 }
}

2014年10月8日 星期三

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(12)–繼續完善新增.修改.刪除功能-2

* 本篇目標

接續上一篇,繼續完成Angular.js的新增.編輯功能

* 上篇回顧

上篇我們依序從BLL.Web API,完成NG的Service call Web API,並在前端的Grid新增了編輯.刪除按鈕,此篇會接續來完成新增.編輯功能,以下是上一篇的最後一張圖。

56eb19ed168248f88a94ccf29bfb85c7

* 新增

因為是SPA頁面,我們會先增一個AddCustomer.html來定義template,藉由ng-model來指定我們的ViewModel欄位。這個html的內容會替換前幾篇我們所定義的ng-view div的內容。

5c5dc2e86b7d4301b5b8f1f1bbe5bd68

透過NG的Route,在最上層的app.js我們可以指定連結為/Customer/Add時指定為Contoller使用CustAddCtrl,html template使用為AddCustomer.html

036b6f056ecd4ae7aa4c86af65aa5285

畫面瀏覽:

4f8a9056dd054e2792b614e8aeaca3ca

新增一個customerAddController.js,基本上邏輯不會太複雜,故用註解來解釋

673569d9d1994e77914b31a731a6ced2

* 編輯

同樣,我們新增一個EditCustomer.html

539bc09bb3ce4091b3c3213b24568aa1

customerEditController.js,這邊又用到一個NG的新東西,因編輯我們透過QueryString來傳遞客戶的ID,$routeParams可以讓我們很方便的去取得參數

f224ffa881d843959f623796c0aaa1bf

* 後記

雖然jQuery程式很精簡好懂,NG則學習曲線較高,但jQuery跟html的耦合性太高,實務上我們常常會遇到一些鳥事,譬如設計師UI大改,客戶功能需求變更…等等,Angular.js將各"職責”分開,html跟srcipts完全不會有衝突,網頁設計師只要給他新的版,我們再套上NG所對應的ng-model即可,而需求變更我也會很清楚的知道要開哪個檔案去擴充。

我們基本上把改有的功能都帶過了,下面幾篇預計就活用前10幾篇的技術,繼續完成我們的需求!

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月7日 星期二

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(10)–開始打造SPA網頁

* 本篇目標

Angular.js切割分層,並改寫成SPA網頁

* SPA

SPA ( Single Page Application),傳統一直POST,一直重新整理的網站在使用者體驗上是比較不好的設計,這也是為什麼Ajax目前已經變成是很普遍的事,而SPA顧名思義就會只有一個網頁,所有網站要做的事都利用Ajax的方式來處理,最顯見的意思就是Gmail,有沒有發現Gmail可以做很多事情,但是整個網頁都是沒有重新整理的。

延伸閱讀  SPA - Single Page Application

* 改寫Angular.js

先來看看目前已經完成的Code,我們逐步重構

489a18c3eb7b4f79aea18324c34a5f9b

1. angular.module模組每個頁面都要載入一次 -> 我們抽成一個.js檔,當成最上層

2. 與WebAPI溝通之程式也應有共用性 -> 抽成CustomerService.js

3. CustCtrl 再頁面上與html同時存在過於雜亂難維護 –> 我們抽成CustomerController

 

實務上我至少會區分以上的架構,接著來逐步改寫:

1 . 宣告一個MainAPP,並將ngRoute及ui.bootstrap模組載入,ngRoute是之後要改SPA的模組,這邊先載進來

17d4708197d2464689cc87d3ec344b7b

並且將ng-app往上層的<html>拉

674fe2335833461b8785fb33c59b6ed8

2.  我們將跟WebAPI溝通的改為一個Service

$q 參數,是一種JavaScript Promise的設計模式,Promise翻譯為承諾,我們將Web請求封裝起來,讓使用此API的程式只知道幾件事:  (1) : 成功了 ! 得到什麼資料 (2) 失敗了 ! 得到錯誤訊息 ,對於怎麼Call,使用這API的人不用太了解,這就是$q回傳的 resolve 及 reject

72fcb794f2024345a2809e4ccd941b40

3. 新增一個customerController.js 將Code複製近來,特別要注意的是,我們需載入CustService參數來使用,我們可以再.then裡面來接回Service成功回傳的值。


32818214c314493fbf20af07202b5842




接著再_Layout.cshtml載入這三個檔案


deb93e09366a4026b686e44c631370d1


這樣我們Customer Index.cshtml就會只剩下html的code了


* 改成SPA網站


但是這樣還不夠,這系列文章我們希望用SPA架構來開發。


先載入Route模組


faadb1636bcb46e8b2e385b5867b1e84


我們利用Angular.js的Route機制來修改,如當瀏覽器網址/Customer的時候,使用CustCtrl Controller,並載入List.html這個檔案


a51fddb298c94a8888e72f46f2260a1e


接著我們將原先的index.cshtml放入List.html檔案


58c6c1ff833f4589bedf738ebb896f21






而指定的List.html內容要載入到哪裡的,就是定義於ng-view


866ce3e9475447568bb05dd363b416e5


如此這樣就輕鬆完成SPA的網站了,且html與scripts與WebAPI Client邏輯都已拆開,問時就能有個明確方向。未來增加新增.修改時,也是透過NG的Route機制,讓我們將ng-view內容做個切換,不重新整理。


延伸閱讀


http://codewala.net/2014/06/16/learning-angularjs-with-asp-net-mvc-part-4/


http://www.infoq.com/cn/news/2011/09/js-promise


https://docs.angularjs.org/api/ng/service/$q


http://www.asp.net/web-api/tutorials/hands-on-labs/build-a-single-page-application-(spa)-with-aspnet-web-api-and-angularjs


 


 


本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月6日 星期一

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(9)–WebAPI實作分頁

* 本篇目標

將WebAPI的資料在後端進行分頁

* Angular.ui.Bootstrap UI

Angular.ui.Bootstrap 能將一些Bootstrap JavaScrip 的功能,使用Angular.js Data Binding的方式來呈現,且CSS樣式還是以Bootstrap為主,是一個還不錯的UI搭配選擇。首先先透過Nuget安裝,並載入。

1298237de5114eb19c0309e6c4a120c2

* 開始擴充 BLL –> Web API –> View

分層的好處就是如果功能要擴充,對我來講會很直覺的一層一層去實作,而不會像所有程式碼都在一起,可維護性就比較差。

BLL層,我們增加兩個參數 : 目前頁數及顯示頁數,回傳總數量

b2222807b33747c7a0d3dce075b24c07

Web API ,向BLL要分頁的資料

e10594f486264e2eb0a1036a96ec0006

可以用瀏覽器來測試,傳入分頁參數

a945e2a229564c27b2ef6905fe86bf9b

View ( Angular.js)

記得之前有稍微提到Angular.js因都模組化,如需要某些功能,可以動態載入,故我們可以載入ui.bootstrap

489a18c3eb7b4f79aea18324c34a5f9b

Html 修改

Angular.UI.Bootstap可以很容易幫我們做到分頁功能,詳細的屬性可以至http://angular-ui.github.io/bootstrap/#/pagination查看,我們就直接看Code吧

a263a28c907b4d478a824bc37e0d5adf

結果畫面

9307a099aff2417cba3f70b8682326cb

* 後記

寫到這邊會發現一點問題,隨著功能越來越多,前端的Code也開始雜亂了,html與scripts的程式碼也開始混再一起,所以下一篇我們就來談談Angular.js的簡單分層方式,並將網頁改成用SPA系統(可不是泡溫泉的系統)。

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月5日 星期日

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(8) - 美化網站工具介紹

* 本篇目標

利用一些 CSS Freamwrok 來快速美化我們的網站

* Bootstrap

開發Web目前Bootstrap已經是必備的技能之一了,甚至ASP.NET網站預設網站也已經全面改用Bootstrap, 如下:

5d07728c23444ba098a1aea2bdc038bb

我們用Nuget升級到目前的版本 3.2.0

139b2fbc829a47b49cedf0aeaf73b249

Bootstrap官網已經寫得很清楚,甚至只要看到順眼的樣式,只要指定個html class,就可把html copy下來,

如前兩天的範例,指定table class="table table-bordered" 就會變成很漂亮的帶框線table

dbd838df68e949c699719e0821b6ede7

f849fdcc41434921890cbf2913456177

其他像input textbox . Button …也只要套個class,就完成美化了,是不是很方便呢!

* Bootstrap主題 – Bootswatch

Bootwatch網站有提供一些免費的主題,讓我們很容易的輕易去更換網站配色,當然可以去買一些付費的template,如Wrapbootstrap,花幾百塊台幣就可以買到一個很完整的網站版型。接下來介紹一下怎麼使用Bootwatch的免費版型來更改樣網站配色。

點選bootstrap.min.css

bdd16d9182414c9cabdd0d4e7315b49d

點開後應該是一大串的css code,我們把這些貼回專案裡bootstrap.min.css

bdd16d9182414c9cabdd0d4e7315b49d

再將選單文字修改一下,這樣很輕鬆就更換配色了!

1033a6d9670648f19f5957faab6cdbc5

* Font Awesome

在以往一些圖示,我們都要設計師做一些ICON,但這個會有一些問題,如設計師死不給(有可能發生)造成時程Delay,或者是ICON大小要做修改,造成失真要重做。Font Awesome是一種以文字呈現圖形的服務,且他跟向量圖一樣是不會隨著大小而失真的,我們一樣使用html標籤 + class 就可以顯示ICON了,且他提供的圖片,我想是非常夠用的。

一樣用Nuget安裝 (有沒有覺得Nuget真的很強大...)

be8a320b748645dfa59ce4fe20424cdd

於Layout.cshtml載入.css

fcbcd99635ed484bb3cd9cfe05c3e769

接著去官網找合適的ICON

fdc0cd573189464f9900643eedb69d8a

套進class,並使用NG的ng-show來判斷是不是像WebAPI取得資料中,來顯示讀取中圖示

c3054489a4f249cdb5941ae21d643e57

完成圖

d36ee5bc7b3e444a9ad8338e4986d2d7

* 後記

現代化開發網站已經有很多工具能幫助我們快速開發了,Devopler通常對UI比較沒有概念,另一個就是某些網頁設計師對css html可能還不是那麼熟悉,用一些工具切出來的版會發生可怕(以前受過table包table網頁版的折磨),現在的話,我會用bootstrap來跟設計師討論,因為bootstrap Responsive Web Design (RWD)是做得非常好的,手機網頁看都會自動變成很好閱讀,故設計師主要會做客製化圖片的部分。接下來後面文章都會利用這些工具來製作我們的網站。

最後介紹一個工具 - placehold.it ,一個很方便的網站服務,當我們與設計師討論好某個區塊圖片向素大小為多少時,我們就可以用指定大小的方式來產生圖片,如:

http://placehold.it/350x150

http://placehold.it/50x50

這樣就可以指定於Img標籤,讓我們先有網站大概的版型樣子,不用等設計師設計出來

<img src=’http://placehold.it/350x150’/>

350x150

 

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月4日 星期六

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(7) - 取得WebAPI資料(Angular.js)

* 本篇目標

利用Angular.js像WebAPI取得資料

* 前言

以往開發前端多半倚賴jQuery,今年接觸到了Google所推出的JavaScript libery , 他是一個前端MVC的Freamwork,Study過後,認為將前端改寫成NG,程式會比較有彈性,故開始投入學習。個人認為學習曲線NG比學習jQuery還要高,本系列文章並不是針對NG做一個詳細介紹,故會採用"做中學"的方式,來實作ASP.NET MVC如何搭配Angular.js做開發。

* Visual Studio 安裝

我們一樣在Web專案使用Nuget安裝

4ae8c68e39ce4cca9b2fe982736d2a4f

會看到Scripts資料夾裡有非常的多的Angular套件,這是因為Angular.js模組化做得非常好,故如果沒有要用到的功能,就不用載入進來,而相關的模組有什麼功能可以用,其實可以google ng加檔名,就可以查到官方文件或文章,如 “ng-resource”。

e7f4127b09af48a0bdd1a59b23ba2450

接著我們打開MVC的 View,Shared資料夾_Layout.cshtml檔案,載入angular.min.js。

_Layout有點像是ASP.NET WebForm的Master Page,可以把一些共用的html,js,css放在這,頁面各自的View就不用存在於重複的程式碼 e.g 選單列。

4280682be0ba4eee9669dd2e0d31bb20

* 修改CustomerController

上一篇我們取得WebAPI資料的方式,是採取C# WebClinet的方式,在Contoller轉成ViewModel在給View,採用Angular.js將會做一些小修改。首先我們將程式碼註解起來。

219dc17ca88d4f54a3c278980a068d79

接著我們改寫View使用Angular.js的語法,會發現Visual Studio 2013 已經很貼心的將NG的語法變為紫色了,這讓開發更加的清楚,以下依步驟做介紹

ng-app : 可以說是Angular.js的起始點,子元素才會看得懂Angular.js的語法

ng-controller : 因為是MVC架構,故我們會在Scripts新增一個Controller的function,並指定這個Div使用CustCtrl

$scope : 可以想成是"前端"的ViewModel,又有點像是C#的Class,可以將變數定義在此,以此例,我們將後端取回的Customer JSON資料,丟給$scope裡的Customer。

$http : 在與後端資料溝通,我們可以使用$http來對Server API進行,POST . GET . PUT .DELETE,以此例我們向我們WebAPI取得資料,丟給$scope裡的Customer;失敗的話則給$scope一個變數error,並秀在Div裡。

$ng-repeat : 此語法可以讓我們很輕鬆的寫出迴圈功能,如Customer裡面的資料,我們將資料一筆一筆讀出來,並變成html table裡的tr列。

8c326a0bc5104c188986a7d4ab413b1e

結果畫面

07a6757c363749109aabd426f4892e7a

* 雙向繫結

在Angular.js的MVC架構,都有Data Binding的特性,也就是今天在Model改變了一些值,或在View改變了一些值,是兩方都會產生變化的。

image

用講的不太清楚,故我們來玩個小範例:

http://jsfiddle.net/kyleshen/5un6argf/

TestCtrl裡面Model有 Day . Name兩個變數,及一個事件 Add,將Day加1

ng-model : 可以指定這個input標籤 對應到Model的名稱

ng-click : 點選Click的時候去執行哪個事件

08cc1b432f954b36b1e13e27d00ef5fb

* 後記

此篇介紹了一些Angular.js的一些基本用法,下一篇預計來換個輕鬆主題,來介紹如何利用一些工具來快速美化我們的網站。

Angular.js逐步學習文章推薦:

男丁格爾Angular.js教學 http://abgne.tw/category/angularjs

黑暗執行緒Angular.js系列 http://blog.darkthread.net/blogs/darkthreadtw/archive/tags/AngularJS/default.aspx

 

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月3日 星期五

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(6) - 取得WebAPI資料

* 本篇目標

建置一個RESTful風格的Web服務

* Web API 2.2

現在開發通常會考慮到多平台,如手機平板等等,但關於資料來源不可能針對每個平台都去寫一樣的Code,早期.NET解決方案有Web Service、WCF Service的應用,.NET Freamwork 4.5後推出了更輕量化的Web API服務,搭配MVC架構開發上變得非常的輕鬆,本系列文章使用Web API 2.2。

延伸閱讀  [Web API] 初探 Web API 筆記

* 建置Web API

我們再UI層新增Web專案時,其實就已經勾選安裝Web API了,如果忘記選擇了,可以透過Nuget安裝。

a8dcf173f2614837b442e02a913799a9

WebAPI開發習慣,我通常會再專案底下建一個API資料夾,接著點選右鍵,加入Web API控制器

f247eb1d2af848babad98b146db3126a

建立以後,她預設會幫我們建立CRUD function,我們就針對每個function去改寫,注意Web API也是MVC架構,命名也是為Controller結尾,但不同的是Web API是繼承ApiController。

9c6601b5d9a54583bdc1d37aab8aae37

接下來我們將Get稍作修改,向BLL層要客戶資料,HttpReponseMessage可以很方便的讓前端知道是否有發生錯誤,並回傳自己定義的Object。

7b24c666c2444fae98ab71461d75553d

接著在瀏覽器執行,輸入 host/api/Customer即可取得我們的資料

a109f7e377e44ef48a866cb63d5a45ad

* 於MVC的Controller及View列出資料

接著我們再專案裡Contoller,新增一個CustomerController

e7bede476978464188a15b911f382cc7

在Controller使用WebClinet像Web API要資料

3dded709ab774d879f9ecd1cf1d1df83

在新增一個View,套入原本樣板的主體Layout

b47227cee9764b49a4fcc1a2ebd5c62b

使用ViewModel,並用好用的Razor語法印出資料

39321e5640db412282e6ee4a0567e661

結果畫面

8dc19f6dfc0745b28cd4d067c85db1f5

* 後記

我認為Web API是個趨勢,未來我也一定會採用這種架構,一方面MVC的Contoller不會有太多跟BLL Service溝通的code,且對於多專案平台,都可向WebAPI取得資料。但實務上我並不會將跟Web API的Code寫在Controller裡,而會是在前端的View,也就是Angular.js登場的時候了!

延伸閱讀ASP.NET MVC - 第一個Web API,Hello Web API

ASP.NET WEB API 心得筆記 (4) WEB API ROUTING

MSDN – MVC Razor語法

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **