2017年12月26日 星期二

[.Net Tool] 使用bootstrap-multiselect實作帶checkbox與optGroup的DropDownList(使用ajax with json或model binding)

說明:
下拉式選單(DropDownList)是網頁常見的元素(element),
如果要做出帶有群組(optGroup),且項目前都有核取方塊(checkbox),如下圖:


該怎麼做呢?


這裡使用bootstrap-multiselect套件,使用BSD 3-Clause License,
商業使用須加上作者的版權聲明。

本例資料來源從Localdb產生,table為Country,如下圖:



並將資料整理成bootstrap-multiselect需要之格式,
如:
var data = [{
    label: 'America',
    children: [{ label: 'Canada', value: '2042101B-A6AF-4603-B04A-10D9257821CD' },
                    { label: 'American', value: '7E35A8AC-D415-4ED3-B572-725ACF7074FB' }]
    }, {
    label: 'Asia',
    children: [{ label: 'Taiwan, ROC', value: 'EB9A0E48-A541-430B-AAEA-C85D98DBA384' },
                    { label: 'Singapore', value: '0A5D7D14-9698-4AAA-B3F6-586EED21D0CD' }]
}];


定義GetAll方法來做這件事:


以下兩張圖是自訂的類別(轉換成Json用)


Controller部分,其中LoadAllCountries取得CountryService中的GetAll,
Update則是取得選擇的country Ids:


View部分,使用jQuery.ajax取得下拉式選單的資料,
使用form表單post選擇的country Ids:


呈現結果:

送出表單後,可取得多選的Ids:


to be continued...

2017年12月5日 星期二

[Network] TCP建立連線與關閉連線機制(connection establishment / termination)

TCP protocol屬於傳輸層(Transport Layer),提供可靠傳輸與流量控制,
host與host溝通需先建立連線,過程共需3次封包傳遞:

用2個封包,可能會發生:
第1次送出的封包delay,client等不到回應,只好再送出SYN封包,
server先收到第2個SYN封包,且完成工作並關閉連線了。
後來第1個SYN封包送到server了,server就會建立多餘的連線...
因此,使用3次封包來回較可靠,俗稱3向交握(3-way handshaking)機制。

交握流程如下圖:



圖中的SYN與ACK,代表該封包的旗標(flag),
在TCP封包的header中,用一6 bits的segment來表示:
[SYN]:000010。
[ACK]:010000。
[SYN,ACK]:010010。

其他segment:
seq:封包序號,由host自己維護,建立連線時+1。
len:封包的資料長度,不包含header。
ack:封包的確認號,建立連線時,為host接收到的序號+1。

對照使用Wireshark截取的封包。

Win:接收視窗,為該host陳述自己的可接受資料的快取byte。
MSS(Maximun Segment Size):表封包一次最大裝載資料byte。
同樣Win下,MSS愈大,傳遞的封包愈少。


下圖是關閉連線的機制。




參考資料:
http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml

2017年11月1日 星期三

[.Net MVC] 使用MVC BundleConfig的{version} wildcard的注意事項


使用ASP.Net MVC預設範本的BundleConfig,
會使用{version}來bundle jQuery套件,如:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));


之前看微軟文件, 使用{version}萬用字元的好處其一是:
  • debug組態:會自動bundle full debug版本。
  • release組態:就bundle min版本。
看起來也很直覺。

但有一次在release組態,我將full debug(jquery-x.x.x.js)的版本拿掉,
發現jquery沒有正確載入,才發現MVC預設會忽略min版本(in the bundles.IgnoreList),
所以應是使用full debug版本bundle與minify,
再加入HttpRuntime.Cache,如下圖紅框處。



因此,在Scripts資料夾下放full debug版本的js或css應該就沒問題了。
to be continued...


參考資料:
https://stackoverflow.com/questions/29254181/bundling-not-working-in-mvc5-when-i-turn-on-release-mode
https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification
https://stackoverflow.com/questions/21270834/asp-net-mvc-bundle-not-rendering-script-files-on-staging-server-it-works-on-dev
http://www.mytecbits.com/microsoft/dot-net/asp-net-mvc-bundle-rendering
http://demo.tc/post/779

2017年10月24日 星期二

[.Net/VS] Could not load file or assembly 'Microsoft.Web.Deployment'與莫名發行失敗(fail no output message)


● 使用VS針對web application使用發行,
出現Could not load file or assembly 'Microsoft.Web.Deployment, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35', 究竟發生什麼事??

原以為是web application需要參考Microsoft.Web.Deployment,
經過一番嘗試之後,
發現在本機(client端)安裝web deploy即可。

安裝完到路徑C:\Program Files,會出現IIS\Microsoft Web Deploy V3資料夾,
裡面會有Microsoft.Web.Deployment.dll,如下圖。



● 發行後,VS左下角狀態列出現發行失敗,且無其他訊息。

可將專案實體資料夾下bin內檔案手動清除,再發行看看。

2017年10月22日 星期日

[.Net/VS] Web Deployment 工作失敗:Microsoft.Web.Deployment.DeploymentManager的類型初始設定式發生例外狀況(threw an exception type initializer)

說明:
使用VS內建發行,點選「驗證連接(Validate Connection)」,
出現如下錯誤訊息。


解法:
搜尋網路解法,有人說要解除Microsoft Web Deploy dbSqlPackage Provider(如下圖所示),
但是我的Server並無安裝該程式。


又看到重新安裝Server上Web deploy的解法,

於是使用Web Platform Installer 5.0安裝:
● web deploy 3.6
● web deploy 3.6 for Hosting Servers
● web deploy 3.6 without bundled SQL support(latest)

再到控制台->解除安裝程式,
找到web deploy 3.6後,點選「變更」,
改成完全安裝就可以了,如下圖。



參考資料:
https://docs.microsoft.com/en-us/iis/publish/using-web-deploy/web-deploy-automatic-backups
https://stackoverflow.com/questions/6351289/web-deployment-task-failed-the-type-initializer-for-microsoft-web-deployment
http://blog.sanc.idv.tw/2014/08/aspnet-web-deploymvciis.html

2017年10月17日 星期二

[.Net MVC] 使用ValidationAttribute與IClientValidatable自訂前後端驗證 (Input Date isn't greater than today)

說明:
之前提過Remote驗證預設沒有後端驗證,
雖然可以自行實作後端驗證。
但MVC提供了自訂驗證(Custom validation),
可自訂驗證邏輯,並含括前後端驗證,
既然是預設的,就來試看看吧。

實作:
首先,新增一類別做驗證,並宣告為sealed,
因該類別單純用來做驗證,
再繼承ValidationAttribute,並override IsValid(object value)方法,
方法內,編寫驗證邏輯。

P.S. 帶ValidationContext的isValid方法,
可存取ViewModel該驗證屬性的資訊。



掛上剛新增的類別,記得要using類別所在namespace。


但沒有觸發前端驗證??


因為繼承ValidationAttribute只有後端驗證,
所以要補上前端驗證,在驗證類別再加上實作IClientValidatable介面,
也就是實作GetClientValidationRules方法。
方法內,需建構ModelClientValidationRule instance,
其中ValidationType傳入字串需要小寫,用來連結前端的html attribute與js方法。


這個rule會render到該html element的attribute。


最後,透過實作jQuery.validator的自訂驗證方法。


前端驗證也觸發了。


參考資料:
http://www.c-sharpcorner.com/UploadFile/abhikumarvatsa/enabling-client-side-validation-on-custom-data-annotations-w/
http://demo.tc/post/687
https://jqueryvalidation.org/jQuery.validator.addMethod/

2017年9月20日 星期三

[.Net MVC/jQuery] add TextBox Numeric/Spinner

說明:
如果想讓TextBox(input element)可以用選的,如下圖:




該怎麼做呢?

作法:
HTML 5有支援Number input type按此可知那些瀏覽器有支援,
在input element內設定type="number",chrome與firefox就可以用選的(spinner)。
但是...,IE 11Edge雖然有支援numeric,但沒有實作spinner XD。

如果不想自己寫css跟js,可以使用jQuery.UI提供的spinner,demo按此
或是Number polyfill

這裡使用jQuery.UI的spinner來試試。
首先使用NuGet或自行下載jQuery.UI package,目前最新版為1.12.1,有相依於jQuery。
再include jquery-ui.css與jquery-ui-1.12.1.js。


這裡遵照unobtrusive的原則,將HTML跟JS分開。

MVC 5.1後,EditorFor可以加HTML attribute的object了。
也可以建立專用的EditorTemplates,類似需求直接掛屬性即可。

執行看看,IE跟Edge都有spinner了。


參考資料:
http://html5please.com/#number
https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#new-features

2017年8月28日 星期一

[.Net MVC] Remote validation example (Input Date isn't greater than today)

說明:
Remote驗證是一種假前端驗證,背後是用ajax呼叫後端Action,
方便開發人員在後端編寫驗證邏輯,不過預設只能在前端觸發。

範例:
首先新增一Controller做驗證,注意Action傳入參數名稱要與ViewModel對應的屬性名稱相同(Model binding)。


在ViewModel該屬性上掛上RemoteAttribute class。
第一個參數是Action name,第二個參數是Controller name。


View部分,使用HtmlHelper產生html element,
需再include jquery、jquery-validate與jquery.validate.unobtrusive.js。

執行網頁後,檢視HTML發現多了remote相關屬性:

切到Network tab,當觸發該欄位時,會送出get request,後端傳回true或false。

實際畫面如下。

結論:
● Remote驗證還是前端驗證,因此不保險,重要驗證還是須通過後端驗證。
● 若觸發欄位無變動,不會送出request,多欄位比較驗證要注意(例:兩個日期比較)。


參考資料:
https://msdn.microsoft.com/en-us/library/system.web.mvc.remoteattribute(v=vs.118).aspx

2017年7月17日 星期一

[jQuery] jQuery plugin DataTables ajax reload 搭配ASP.NET MVC

說明:
使用jQuery plugin DataTables來呈現資料,與資料異動後做reload。


做法:
資料來源為localDB,使用EF code first定義一簡單的Model:

Controller部分,回傳json包在key為data的object內:

最後是View部分:

實際畫面:



參考資料:
https://datatables.net/reference/option/
https://datatables.net/examples/server_side/post.html
http://www.techstrikers.com/Articles/jquery-datatable-bind-json-using-asp.net-mvc5.php
https://datatables.net/reference/api/ajax.reload()
https://editor.datatables.net/examples/simple/inTableControls.html
https://datatables.net/forums/discussion/21164/disable-sorting-of-one-column
https://stackoverflow.com/questions/30627026/jquery-datatables-how-to-add-an-edit-and-delete-option

2017年6月29日 星期四

[jQuery] refresh jsTree(3.2.1) 搭配ASP.NET MVC與json

說明:
使用jQuery plugin jsTree可在網頁上呈現樹狀結構資料,若需要refresh或reload資料,該如何做?


做法:

新增jsTree的物件Model。資料來源使用json文字檔,來簡單模擬資料變更。


在Controller加入取得Tree Nodes的Action Method,
其中使用HostingEnvironment.MapPath取代Server.MapPath,
因Server.MapPath在HttpContext類別下,需有request才可使用。

在View建立jsTree的instance與refreshTree function,新增一button做重新整理。














參考資料:
http://www.dotnetqueries.com/Article/62/implementing-jstree-in-asp-net-mvc-with-json-data
https://www.jstree.com/api/#/?q=.jstree Event
https://www.jstree.com/api/#/?q=(
https://msdn.microsoft.com/zh-tw/library/system.web.httpcontext(v=vs.110).aspx

2017年6月25日 星期日

[EF] 使用Entity Framework code first紀錄

● VS 2013與EF6預設沒有code first精靈,該如何解決?
Ans: 安裝Entity Framework 6 Tools for Visual Studio 2012 & 2013

● 不透過精靈,使用code first建立新的資料庫?
to be continued...

2017年5月30日 星期二

[.Net/C#] foreach如何存取集合(Iterator/IEnumerable/IEnumerator/yield return)

說明:
foreach是用來對集合元素做巡覽/列舉的動作,透過Iterator來實作,
而Iterator是一種模式,在不暴露集合類別下,提供對集合類別依序巡覽的方法,
在.Net裡,已經將Iterator包好了,實作IEnumerable與IEnumerator即可。


什麼是IEnumerable?看下圖可知實作此介面提供一方法GetEnumerator(),
讓我們可以取得集合元素。



那IEnumerator呢? 提供實作iterator所需的方法與屬性。



也就是使用foreach in,編譯器會去找要巡覽的集合類別裡的GetEnumerator(),
然後執行IEnumerator內的MoveNext(),若回傳True,再取Current的值,
直到MoveNext回傳為False。


C# 1.0實作:
想巡覽Book集合類別,需實作IEnumerable與IEnumerator。







C# 2.0提供IEnumerable與IEnumerator的泛型,
可傳入巡覽元素的型別,減少裝箱與型別轉換的問題,
(因Current非泛型版本回傳值為object)。





C#2.0更提供yield return免除自己實作IEnumerator的困擾,
編譯器看到yield return會自動建立IEnumerator類別並回傳IEnumerator型別。



最後一樣可巡覽集合類別。