2013年4月23日 星期二

AngularJS in Web Form 之 SPA 明知山有虎 偏向虎山行 下篇

在上篇我們搞定了 Web API

但是 Web API 只是個負責提供資料查詢的角色

SPA (single page application) 顧名思義 一頁打天下

其中心思想自然落在 JavaScript 上頭

J蛞蝓是神兵 但是要用來 hold住 SPA 的小宇宙 略顯吃力

回顧上篇的 JavaScript DOM事件(click) → AJAX → callback → 更新DOM

這整串的流程都寫在一起

這樣跟把所有的程式碼寫在頁面.cs檔的一個 click 事件中 是差不多的意思

義大利麵式的 code 難以擴充維護





我願意相信團隊成員都有強大的 coding 能力 及 良好的代碼習慣 並且遵守一切共能訂定的規範......

那我就太傻太天真了





看清事實吧 我們需要一些 強大 簡單 美好的 框架 來拯救我們不堪一擊的 測試 跟 需求變更

因此 JavaScript 的 mv* framework 開始風行

但是另一項災難就是 這種 mv* framework 似乎各大行家都要搞一套出來證明自己風騷

除了常見的四天王之外

  Backbone.js

  Knockout.js

  Ember.js

  Angular.js

還可能有些聽都沒聽過的...

12种JavaScript MVC框架之比较





該怎麼選擇?到底哪個最好?有種永遠學不完的感覺...

其實很好挑 順從人類的性本能直覺 就跟挑OO一樣想跟誰OO就挑誰

挑你愛的 挑你順眼的 挑你爽的 挑你一看見它就衝動的

就算是 mv* framework 永遠會推陳出新 只要有愛就沒問題對吧





以上閒聊以下正題

正題就是繼上回玩過 Knockout 之後 這回我又搞上 Angular 啦

沒辦法 誰叫男人就是喜新厭舊的動物





馬上把上篇的東東 改寫成 Angular

但是只改寫太無趣 且無法彰顯 Angular 的強大之處

首先先從 Web API 下手 我們再增加一個 RoleDetail 類 讓它跟 Role 類 有主表明細的關係

然後修改一下 Web API 讓使用 id 的 GET 方法 傳回 RoleDetail

POST PUT 跟 Delete 則增加對 RoleDetail 的處理

POST 跟 PUT 所需的傳入參數 可能是我比較笨的緣故試不出來怎麼傳兩個類別

但是在建立一個 DTO 包含這兩個類別 卻行得通 好吧 就這麼辦吧

HTML 變這樣 ...

JS 變這樣 ...





欲知更多細節 請洽 http://docs.angularjs.org/api/

哈哈 不是我(就是想)想偷懶 而是這篇就說得太明白的話 後面沒東西好玩了

況且這麼多的 framework 先感受他的風格 再去了解細節也不遲 不要想 用直覺去感受





定番截圖





飯粒檔:http://www.mediafire.com/download/8jkajx99i2192jn/testAPI.zip

2013年4月22日 星期一

Web API in Web Form 之 SPA 明知山有虎 偏向虎山行 上篇

休息人人愛 REST也是

我亂講的 是不是人人愛我不知 至少是最近的顯學

而 ASP.NET Web API 則是微軟用他來證明自己也很潮 很RESTful

第一次參見 Web API 是在 MVC 4 上

他們相性很合直接使用無大礙

Web Form 則沒那麼好的待遇 誰叫微軟也是比較寵么子

同是自家 沒有不能用的道理 只是需要一些手段

就讓咱們來瞧瞧虎山之途





一隻老虎:是否2012

如果是 2012 的話 在加入新項目 可以直接選 Web APT 控制器類別

如果沒有 就直接建一般的類別 然後繼承 ApiController (需要將 System.Web.Http 加入參考)

類別名稱務必叫做 xxxController 預設命名多個 1 是陷阱

隨附範例代碼





設定 Routes

因為配合 MVC 所以它也是靠 Routes 來辨識 API 的路徑的

請在 Global.asax 設定以下東東 (需要將 System.Net.Http 跟 System.Web.Http.WebHost 加入參考)





需要 Json.NET

輸入 http://localhost:22354/api/Roles 如果能看到 JSON 的話代表我們通過第一階段

如果報錯 無法載入檔案或組件 'Newtonsoft.Json... 的話

沒有錯 我們需要Json.NET

定番 NuGet 一下搞定





接下來來看看怎麼玩 CRUD

首先需要一個 Role 類





再來當然是修改 RolesController 使他可以 CRUD 剛剛的 Role類

這裡先以 靜態的 List 來模仿 DB





接下來需要一個頁面 因為是 SPA 所以用一般 html 也沒所謂

寫些按鈕搭 JQuery 來測試 Get Post Put Delete

HTML:

JS:





截圖

2013年3月28日 星期四

mongodb in ASP.NET 之 第一次切芒果就上手

mangle...





喔耶~ NoSQL

喔耶~ BSON 百度

喔耶~ mongodb Wiki





要是以為我會寫介紹文 就太傻太天真

直接玩弄





截圖





testQuery.aspx

    <form id="form1" runat="server">
        name:<asp:TextBox ID="name_tb" runat="server"></asp:TextBox>
        age:<asp:TextBox ID="ageHead_tb" runat="server"></asp:TextBox>
        ~<asp:TextBox ID="ageEnd_tb" runat="server"></asp:TextBox>
        <asp:CheckBox ID="male_cb" runat="server" Text="Male" />
        <asp:CheckBox ID="female_cb" runat="server" Text="Female" />
        <asp:Button ID="Query" runat="server" Text="Query" OnClick="Query_Click" />
        <asp:GridView ID="show_gv" runat="server" AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField DataField="_id" HeaderText="_id" />
                <asp:BoundField DataField="name" HeaderText="name" />
                <asp:BoundField DataField="age" HeaderText="age" />
                <asp:BoundField DataField="gender" HeaderText="gender" />
            </Columns>
        </asp:GridView>
    </form>




testQuery.aspx.cs

using System;
using System.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Linq;

namespace testMongo
{
    public partial class testQuery : System.Web.UI.Page
    {
        private MongoCollection memberCollection = GetMemberCollection();

        protected void Query_Click(object sender, EventArgs e)
        {
            bool ckMale, ckFemale;
            if (
                (!male_cb.Checked && !female_cb.Checked) ||
                (male_cb.Checked && female_cb.Checked)
            )
            {
                ckMale = true;
                ckFemale = false;
            }
            else
            {
                ckMale = ckFemale = male_cb.Checked;
            }
            int ageHead =
                string.IsNullOrEmpty(ageHead_tb.Text)
                ? 0
                : Convert.ToInt32(ageHead_tb.Text);
            int ageEnd =
                string.IsNullOrEmpty(ageEnd_tb.Text)
                ? int.MaxValue
                : Convert.ToInt32(ageEnd_tb.Text);
            IQueryable q = memberCollection.AsQueryable<Member>().Where(
                x =>
                    x.name.Contains(name_tb.Text) &&
                    x.age >= ageHead &&
                    x.age <= ageEnd &&
                    (
                        x.gender == ckMale ||
                        x.gender == ckFemale
                    )
            );
            IMongoQuery mongoQuery = (q as MongoQueryable<Member>).GetMongoQuery();
            show_gv.DataSource = memberCollection.FindAs<Member>(mongoQuery);
            show_gv.DataBind();
        }

        private static MongoCollection<Member> GetMemberCollection()
        {
            MongoServer server = MongoServer.Create("mongodb://192.168.7.25:27017");
            MongoDatabase database = server.GetDatabase("test");
            MongoCollection<Member> member = database.GetCollection<Member>("member");
            return member;
        }
    }
}




截圖





testSaveMember.aspx

    <form id="form1" runat="server">
        name:<asp:TextBox ID="name_tb" runat="server"></asp:TextBox>
        age:<asp:TextBox ID="age_tb" runat="server"></asp:TextBox>
        <asp:RadioButton ID="male_rb" runat="server" Checked="True" GroupName="Gender" Text="Male" />
        <asp:RadioButton ID="female_rb" runat="server" GroupName="Gender" Text="Female" />
        <asp:Button ID="insert" runat="server" OnClick="insert_Click" Text="Insert" />
        <br />
        _id:<asp:TextBox ID="id_tb" runat="server"></asp:TextBox>
        <asp:Button ID="update" runat="server" Text="Update" OnClick="update_Click" />
        <asp:Button ID="delete" runat="server" Text="Delete" OnClick="delete_Click" />
        <asp:GridView ID="show_gv" runat="server" AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField DataField="_id" HeaderText="_id" />
                <asp:BoundField DataField="name" HeaderText="name" />
                <asp:BoundField DataField="age" HeaderText="age" />
                <asp:BoundField DataField="gender" HeaderText="gender" />
            </Columns>
        </asp:GridView>
    </form>




testSaveMember.aspx.cs


using System;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;

namespace testMongo
{
    public partial class testSaveMember : System.Web.UI.Page
    {
        private MongoCollection memberCollection = GetMemberCollection();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack) return;
            BindGridViwe();
        }

        private void BindGridViwe()
        {
            show_gv.DataSource = memberCollection.FindAllAs(typeof(Member));
            show_gv.DataBind();
        }

        protected void insert_Click(object sender, EventArgs e)
        {
            SaveMember(
                name: name_tb.Text,
                age: int.Parse(age_tb.Text),
                gender: male_rb.Checked
            );
        }

        protected void update_Click(object sender, EventArgs e)
        {
            SaveMember(
                _id: new ObjectId(id_tb.Text),
                name: name_tb.Text,
                age: int.Parse(age_tb.Text),
                gender: male_rb.Checked
            );
        }

        protected void delete_Click(object sender, EventArgs e)
        {
            DeleteMember(new ObjectId(id_tb.Text));
            BindGridViwe();
        }

        private void SaveMember(string name, int age, bool gender)
        {
            SaveMember(ObjectId.Empty, name, age, gender);
        }

        private void SaveMember(ObjectId _id, string name, int age, bool gender)
        {
            Member member = new Member { _id = _id, name = name, age = age, gender = gender };
            memberCollection.Save(member);
            BindGridViwe();
        }

        private void DeleteMember(ObjectId _id)
        {
            IQueryable q = memberCollection.AsQueryable<Member>().Where(x => x._id == _id);
            IMongoQuery mongoQuery = (q as MongoQueryable<Member>).GetMongoQuery();
            memberCollection.Remove(mongoQuery);
        }

        private static MongoCollection<Member> GetMemberCollection()
        {
            MongoServer server = MongoServer.Create("mongodb://192.168.7.25:27017");
            MongoDatabase database = server.GetDatabase("test");
            MongoCollection<Member> member = database.GetCollection<Member>("member");
            return member;
        }
    }
}