2017年11月18日 星期六

網頁輸入頁面Enter鍵處理元件(KeyDownProcess Version:1.65)

function KeyDownProcess(e) {
    //-----------------------------------------------------------
    //網頁親和性輸入控制元件
    //元件功能:可以讓網頁資料的輸入更親切,功能如下:
    //1.按下Enter鍵自動找到下一個可輸入輸入元件
    //2.按下Enter鍵自動找尋submit按鍵,如果找到則模擬Click的功能
    //3.當輸入元件設定唯讀時,按下backspace鍵時,防止網頁轉址
    //4.支援無障礙導覽設定
    //5.支援Firefox、Google Chrome瀏覽器
    //6.支援按下shift鍵全域變數ShiftKeyDown(可實作連選)
    //7.支援頁面元件已輸入資料偵測(全域變數:CursorUserChanged CursorUserChangedDetect 可實作window.onbeforeunload confirm)
    //版本:1.65(2016.11.18)-Microsoft Visual Studio 2017 調校後版本(V1.00)
    //作者:科碩資訊有限公司
    //引用本元件,請保留作者和版本資訊
    //連絡mail:cursor@cursorinfo.com.tw
    //------------------------------------------------------------
    w3cEvent = e;
    ShiftKeyDown = false;
    _beforeunloadTarget = '';
    CursorUserChanged = false;
    var kv = 0;
    var rv = false;
    var isTextarea = false;
    var currentId = null; //目前元件
    var ex;
    var isAll = typeof (document.all) === "object";
    if (isAll) {
        ShiftKeyDown = event.shiftKey;
        ex = event;
        kv = ex.keyCode;
        isTextarea = (ex.srcElement.tagName === "TEXTAREA");
        currentId = ex.srcElement.id === undefined ? '' : ex.srcElement.id;
    }
    else {
        ShiftKeyDown = e.shiftKey;
        ex = e;
        kv = ex.which * 1;
        isTextarea = (ex.target === "[object HTMLTextAreaElement]");
        currentId = ex.target.id === undefined ? '' : ex.target.id;
    }
    switch (kv) {
        case 13:
            if (ex.srcElement.tagName === "A" || (ex.srcElement.tagName === "INPUT" && ex.srcElement.type === "BUTTON"))
                return true;
            if ((currentId.length === 0))
                return false;
            if (isTextarea === true) {
                rv = isTextarea;
            }
            else {
                var cts = isAll ? document.all : document.getElementsByTagName('*');
                var cid = "";
                var queryBu = null;
                var beginNext = false; //開始比對是否為輸入元件
                var nextInput = null; //下一個輸入元件
                var specialSubmitId = "textQueryBU"; //指定特例的submit id
                var exceptionSubmitId = "waitting"; //指定例外的submit Id
                for (ii = 0; ii < cts.length; ii++) {
                    if (cts[ii].type === null || cts[ii].id === null)
                        continue;
                    if (cts[ii].id === currentId) {
                        beginNext = true;
                        continue;
                    }
                    if (beginNext === true && (cts[ii].id.indexOf(specialSubmitId) > -1 || ((cts[ii].type === "submit" || cts[ii].type === "image") && cts[ii].id.indexOf(exceptionSubmitId) === -1))) {
                        queryBu = cts[ii]; //找到submit元件
                        break;
                    }
                    else if (beginNext === true && (cts[ii].type === "text" || cts[ii].type === "textarea" || cts[ii].type === "password") && cts[ii].readOnly === false && cts[ii].style.display !== "none") {
                        nextInput = cts[ii]; //找到下一個文字輸入元件
                        break;
                    }
                }
                if (null !== queryBu) {
                    setTimeout("doClickId('" + queryBu.id + "');", 100);
                    rv = false;
                }
                else if (null !== nextInput && nextInput.offsetWidth !== 0) {
                    try {
                        nextInput.focus();
                    } catch (Error) { return true; }
                    rv = false;
                }
            }
            break;
        case 8:
            if (currentId.length > 0)
                return !document.getElementById(currentId).readOnly;
            else
                return true;
            break;
        default:
            rv = true;
            CursorUserChanged = typeof CursorUserChangedDetect === 'undefined' ? false : CursorUserChangedDetect;
            break;
    }
    return rv;
}
//找到第一個可輸入元件,並設定focus
function getFirstInputControl() {
    var inputs = document.all && typeof (document.all) === "object" ? document.all : document.getElementsByTagName('input');
    for (i = 0; i < inputs.length; i++) {
        if ((inputs[i].type === "text" || inputs[i].type === "textarea") && inputs[i].readOnly === false && inputs[i].offsetWidth !== 0) {
            try { inputs[i].focus(); } catch (error) { }
            break;
        }
    }
}

2017年9月2日 星期六

糟糕,HTTP轉HTTPS WCF Web服務失效了!

一、問題描述:

Microsoft WCF(Windows Communication Foundation)可以說是SOA 最佳實作技術,最主要的概念包含『鬆散偶合力』 以及 『軟體服務』。而SOA全名為 Service Oriented Architecture。這些名詞和概念不是本文的重點,讀者可以自行在網路上查到相關資料。

今天的問題是建置使用WCF服務的網站,如果由HTTP轉為HTTPS,預設情況下WCF服務是無法正常運作的,必須調整Web.config的serviceModel設定,讓我們來看看該如何調整?

二、實作解決方案:

以下是可正常運作的設定:

<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpBindingConfig">
        </binding>
        <binding name="webHttpsBindingConfig">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>

      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="behaviorName">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="CmsP.Ctrl.Buyone.BuyoneWCF">
        <endpoint address="" behaviorConfiguration="behaviorName" bindingConfiguration="webHttpBindingConfig" binding="webHttpBinding" contract="mycontract" />
        <endpoint address="" behaviorConfiguration="behaviorName" bindingConfiguration="webHttpsBindingConfig" binding="webHttpBinding" contract="mycontract" />
      </service>
    </services>
  </system.serviceModel>

 ※標示紅色字體部分為HTTPS運作的相關設定

2017年1月21日 星期六

在GridView中如何Confirm CheckBox On Client Click

問題說明:
在系統實作的過程有可能會遇到需要在GridView中加入CheckBox元件,當使用者觸發OnCheckedChanged時,希望可以先啟動讓使用者確認異動的視窗。

<asp:templatefield footertext="序號" headertext="序號";>
<itemtemplate;>
<asp:checkbox AutoPostBack="True" id="selectedCB" oncheckedchanged="selectedCB_OnCheckedChanged" runat="server";></asp:checkbox;>
<asp:label id="indexNo" runat="server";></asp:label;>
</itemtemplate;>
<itemstyle horizontalalign="Justify" width="6%";>
</itemstyle;>
</asp:templatefield;>

上面布署的CheckBox元件,當使用者觸發CheckedChanged 後,會直接回送至伺服器,處理selectedCB_OnCheckedChanged even,要如何在Page PostBack前,觸發Confirm視窗呢?又如何讓完成的方法可以反覆使用呢?

我的作法:
1、將元件的布署修改如下:(取消AutoPostBack)

<asp:templatefield footertext="序號" headertext="序號";>
<itemtemplate;>
<asp:checkbox  id="selectedCB" oncheckedchanged="selectedCB_OnCheckedChanged" runat="server";></asp:checkbox;>
<asp:label id="indexNo" runat="server";></asp:label;>
</itemtemplate;>
<itemstyle horizontalalign="Justify" width="6%";>
</itemstyle;>
</asp:templatefield;>

2、掛上Client 端jQuery Fuction

function CancelOrChanged4CB(idFixName) {
$("input[type='checkbox']").on('change', function (e) {
            if ($(this).attr('id').indexOf(idFixName) === -1)
                return;
            if ($(this).prop('checked') === false) {
                if (confirm('確定取消報名嗎?') === false) {
                    $(this).prop('checked', true);
                    return;
                }
            }
            else {
                if (confirm('確定報名嗎?') === false) {
                    $(this).prop('checked', false);
                    return;
                }
            }
            __doPostBack($(this).attr('id'), '');
        });
}

3、在需要啟動CheckBox Confirm的頁面,加入下面jQuery程式碼:

$(window).load(function () {
        CancelOrChanged4CB('selectedCB');
    });

結語:
上面的 CancelOrChanged4CB function是可以重複啟動的。所以可以加入自建的jQuery lib中等候呼叫。

網頁輸入頁面Enter鍵處理元件(KeyDownProcess Version:1.64)

修正:無障礙按鍵不正常問題

function KeyDownProcess(e) {
    //-----------------------------------------------------------
    //網頁親和性輸入控制元件
    //元件功能:可以讓網頁資料的輸入更親切,功能如下:
    //1.按下Enter鍵自動找到下一個可輸入輸入元件
    //2.按下Enter鍵自動找尋submit按鍵,如果找到則模擬Click的功能
    //3.當輸入元件設定唯讀時,按下backspace鍵時,防止網頁轉址
    //4.支援無障礙導覽設定
    //5.支援Firefox、Google Chrome瀏覽器
    //6.支援按下shift鍵全域變數ShiftKeyDown(可實作連選)
    //7.支援頁面元件已輸入資料偵測(全域變數:CursorUserChanged CursorUserChangedDetect 可實作window.onbeforeunload confirm)
    //版本:1.64(2016.1.22)
    //作者:科碩資訊有限公司
    //引用本元件,請保留作者和版本資訊
    //連絡mail:cursor@cursorinfo.com.tw
    //------------------------------------------------------------
    w3cEvent = e;
    ShiftKeyDown = false;
    _beforeunloadTarget = '';
    CursorUserChanged = false;
    var kv = 0;
    var rv = false;
    var isTextarea = false;
    var currentId = null; //目前元件
    var ex;
    var isAll = typeof (document.all) == "object";
    if (isAll) {
        ShiftKeyDown = event.shiftKey;
        ex = event;
        kv = ex.keyCode;
        isTextarea = (ex.srcElement.tagName == "TEXTAREA");
        currentId = ex.srcElement.id == undefined ? '' : ex.srcElement.id;
    }
    else {
        ShiftKeyDown = e.shiftKey;
        ex = e;
        kv = ex.which * 1;
        isTextarea = (ex.target == "[object HTMLTextAreaElement]");
        currentId = ex.target.id == undefined ? '' : ex.target.id;
    }
    switch (kv) {
        case 13:
            if (ex.srcElement.tagName == "A" || (ex.srcElement.tagName == "INPUT" && ex.srcElement.type == "BUTTON"))
                return true;
            if ((currentId.length == 0))
                return false;
            if (isTextarea == true) {
                rv = isTextarea;
            }
            else {
                var cts = isAll ? document.all : document.getElementsByTagName('*');
                var cid = "";
                var queryBu = null;
                var beginNext = false; //開始比對是否為輸入元件
                var nextInput = null; //下一個輸入元件
                var specialSubmitId = "textQueryBU"; //指定特例的submit id
                var exceptionSubmitId = "waitting"; //指定例外的submit Id
                for (ii = 0; ii < cts.length; ii++) {
                    if (cts[ii].type == null || cts[ii].id == null)
                        continue;
                    if (cts[ii].id == currentId) {
                        beginNext = true;
                        continue;
                    }
                    if (beginNext == true && (cts[ii].id.indexOf(specialSubmitId) > -1 || ((cts[ii].type == "submit" || cts[ii].type == "image") && cts[ii].id.indexOf(exceptionSubmitId) == -1))) {
                        queryBu = cts[ii]; //找到submit元件
                        break;
                    }
                    else if (beginNext == true && (cts[ii].type == "text" || cts[ii].type == "textarea" || cts[ii].type == "password") && cts[ii].readOnly == false && cts[ii].style.display != "none") {
                        nextInput = cts[ii]; //找到下一個文字輸入元件
                        break;
                    }
                }
                if (null != queryBu) {
                    setTimeout("doClickId('" + queryBu.id + "');", 100);
                    rv = false;
                }
                else if (null != nextInput && nextInput.offsetWidth != 0) {
                    try {
                        nextInput.focus();
                    } catch (Error) { return true; }
                    rv = false;
                }
            }
            break;
        case 8:
            if (currentId.length > 0)
                return !document.getElementById(currentId).readOnly;
            else
                return true;
            break;
        default:
            rv = true;
            CursorUserChanged = typeof CursorUserChangedDetect == 'undefined' ? false : CursorUserChangedDetect;
            break;
    }
    return rv;
}

//實做模擬Click的功能
function doClickId(source) {
    var o = document.getElementById(source);
    if (document.all && typeof (document.all) == "object") //IE
        o.click();
    else {
        if (document.createEvent) {
            var e = document.createEvent('MouseEvent');
            e.initEvent('click', true, false);
            o.dispatchEvent(e);
        } else {
            o.fireEvent('onclick');
        }
    }
}

2016年12月17日 星期六

網頁輸入頁面Enter鍵處理元件(KeyDownProcess Version:1.62)

#KeyDownProcess加入可實作 window.onbeforeunload confirm功能
#doClickId還原模擬
function KeyDownProcess(e) {
    //-----------------------------------------------------------
    //網頁親和性輸入控制元件
    //元件功能:可以讓網頁資料的輸入更親切,功能如下:
    //1.按下Enter鍵自動找到下一個可輸入輸入元件
    //2.按下Enter鍵自動找尋submit按鍵,如果找到則模擬Click的功能
    //3.當輸入元件設定唯讀時,按下backspace鍵時,防止網頁轉址
    //4.支援無障礙導覽設定
    //5.支援Firefox、Google Chrome瀏覽器
    //6.支援按下shift鍵全域變數ShiftKeyDown(可實作連選)
    //7.支援頁面元件已輸入資料偵測(全域變數:_CursorUserChanged _CursorUserChangedDetect 可實作window.onbeforeunload confirm)
    //版本:1.62(2016.12.17)
    //作者:科碩資訊有限公司
    //引用本元件,請保留作者和版本資訊
    //連絡mail:cursor@cursorinfo.com.tw
    //------------------------------------------------------------
    w3cEvent = e;
    ShiftKeyDown = false;
    _CursorUserChanged = false;
    _CursorUserChangedDetect = false;
    var kv = 0;
    var rv = false;
    var isTextarea = false;
    var currentId = null; //目前元件
    var ex;
    var isAll = typeof (document.all) == "object";
    if (isAll) {
        ShiftKeyDown = event.shiftKey;
        ex = event;
        kv = ex.keyCode;
        isTextarea = (ex.srcElement.tagName == "TEXTAREA");
        currentId = ex.srcElement.id == undefined ? '' : ex.srcElement.id;
    }
    else {
        ShiftKeyDown = e.shiftKey;
        ex = e;
        kv = ex.which * 1;
        isTextarea = (ex.target == "[object HTMLTextAreaElement]");
        currentId = ex.target.id == undefined ? '' : ex.target.id;
    }
    switch (kv) {
        case 13:
            if (isAll) {
                if (ex.srcElement.tagName == "A" || (ex.srcElement.tagName == "INPUT" && ex.srcElement.type == "BUTTON"))
                    return true;
            }
            if ((currentId.length == 0))
                return false;
            if (isTextarea == true) {
                rv = isTextarea;
            }
            else {
                var cts = isAll ? document.all : document.getElementsByTagName('*');
                var cid = "";
                var queryBu = null;
                var beginNext = false; //開始比對是否為輸入元件
                var nextInput = null; //下一個輸入元件
                var specialSubmitId = "textQueryBU"; //指定特例的submit id
                var exceptionSubmitId = "waitting"; //指定例外的submit Id
                for (ii = 0; ii < cts.length; ii++) {
                    if (cts[ii].type == null || cts[ii].id == null)
                        continue;
                    if (cts[ii].id == currentId) {
                        beginNext = true;
                        continue;
                    }
                    if (beginNext == true && (cts[ii].id.indexOf(specialSubmitId) > -1 || ((cts[ii].type == "submit" || cts[ii].type == "image") && cts[ii].id.indexOf(exceptionSubmitId) == -1))) {
                        queryBu = cts[ii]; //找到submit元件
                        break;
                    }
                    else if (beginNext == true && (cts[ii].type == "text" || cts[ii].type == "textarea" || cts[ii].type == "password") && cts[ii].readOnly == false && cts[ii].style.display != "none") {
                        nextInput = cts[ii]; //找到下一個文字輸入元件
                        break;
                    }
                }
                if (null != queryBu) {
                    setTimeout("doClickId('" + queryBu.id + "');", 100);
                    rv = false;
                }
                else if (null != nextInput && nextInput.offsetWidth != 0) {
                    try {
                        nextInput.focus();
                    } catch (Error) { return true; }
                    rv = false;
                }
            }
            break;
        case 8:
            if (currentId.length > 0)
                return !document.getElementById(currentId).readOnly;
            else
                return true;
            break;
        default:
            rv = true;
            _CursorUserChanged = _CursorUserChangedDetect !== undefined && _CursorUserChangedDetect === true ? true : false;
            break;
    }
    return rv;
}

function doClickId(source) {
    var o = document.getElementById(source);
    if (document.all && typeof (document.all) == "object") //IE
        o.click();
    else {
        if (document.createEvent) {
            var e = document.createEvent('MouseEvent');
            e.initEvent('click', true, false);
            o.dispatchEvent(e);
        } else {
            o.fireEvent('onclick');
        }
    }
}

2016年1月29日 星期五

網頁輸入頁面Enter鍵處理元件(KeyDownProcess Version:1.61)


##更新實作模擬Click的方法
function KeyDownProcess(e) {
    //-----------------------------------------------------------
    //網頁親和性輸入控制元件
    //元件功能:可以讓網頁資料的輸入更親切,功能如下:
    //1.按下Enter鍵自動找到下一個可輸入輸入元件
    //2.按下Enter鍵自動找尋submit按鍵,如果找到則模擬Click的功能
    //3.當輸入元件設定唯讀時,按下backspace鍵時,防止網頁轉址
    //4.支援無障礙導覽設定
    //5.支援IE、Firefox、Google Chrome瀏覽器
    //6.支援按下shift鍵全域變數ShiftKeyDown
    //版本:1.61(2016.01.30)
    //作者:科碩資訊有限公司
    //引用本元件,請保留作者和版本資訊
    //連絡mail:cursor@cursorinfo.com.tw
    //------------------------------------------------------------
    w3cEvent = e;
    ShiftKeyDown = false;
    var kv = 0;
    var rv = false;
    var isTextarea = false;
    var currentId = null; //目前元件
    var ex;
    var isAll = typeof (document.all) == "object";
    if (isAll) {
        ShiftKeyDown = event.shiftKey;
        ex = event;
        kv = ex.keyCode;
        isTextarea = (ex.srcElement.tagName == "TEXTAREA");
        currentId = ex.srcElement.id == undefined ? '' : ex.srcElement.id;
    }
    else {
        ShiftKeyDown = e.shiftKey;
        ex = e;
        kv = ex.which * 1;
        isTextarea = (ex.target == "[object HTMLTextAreaElement]");
        currentId = ex.target.id == undefined ? '' : ex.target.id;
    }
    switch (kv) {
        case 13:
            if (isAll) {
                if (ex.srcElement.tagName == "A" || (ex.srcElement.tagName == "INPUT" && ex.srcElement.type == "BUTTON"))
                    return true;
            }
            if ((currentId.length == 0))
                return false;
            if (isTextarea == true) {
                rv = isTextarea;
            }
            else {
                var cts = isAll ? document.all : document.getElementsByTagName('*');
                var cid = "";
                var queryBu = null;
                var beginNext = false; //開始比對是否為輸入元件
                var nextInput = null; //下一個輸入元件
                var specialSubmitId = "textQueryBU"; //指定特例的submit id
                var exceptionSubmitId = "waitting"; //指定例外的submit Id
                for (ii = 0; ii < cts.length; ii++) {
                    if (cts[ii].type == null || cts[ii].id == null)
                        continue;

                    if (cts[ii].id == currentId) {
                        beginNext = true;
                        continue;
                    }
                    if (beginNext == true && (cts[ii].id.indexOf(specialSubmitId) > -1 || ((cts[ii].type == "submit" || cts[ii].type == "image") && cts[ii].id.indexOf(exceptionSubmitId) == -1))) {
                        queryBu = cts[ii]; //找到submit元件
                        break;
                    }
                    else if (beginNext == true && (cts[ii].type == "text" || cts[ii].type == "textarea" || cts[ii].type == "password") && cts[ii].readOnly == false && cts[ii].style.display != "none") {
                        nextInput = cts[ii]; //找到下一個文字輸入元件
                        break;
                    }
                }
                if (null != queryBu) {
                    setTimeout("doClickId('" + queryBu.id + "');", 100);
                    rv = false;
                }
                else if (null != nextInput && nextInput.offsetWidth != 0) {
                    try {
                        nextInput.focus();
                    } catch (Error) { return true; }
                    rv = false;
                }
            }
            break;
case 8:
            if (currentId.length > 0)
                return !document.getElementById(currentId).readOnly;
            else
                return true;
            break;
        default:
            rv = true;
            break;
    }
    return rv;
}

//實做模擬Click的功能
function doClickId(source) {
    var o = document.getElementById(source);
    if (!o.addEventListener) {
        o.attachEvent('onclick', onClick);
    } else {
        o.addEventListener('click', onClick, false);
    }
}

Windows Server 2012 R2 IIS 裝載WCF失敗解決方案


一、問題說明
Windows Communication Foundation (WCF) 是用於建置服務導向應用程式的架構。
ASP.NET可以快速建置WCF服務,讓網站資料傳遞更為輕便,大有取代Web Service的趨勢。
當我們使用Visual Studio建置包含WCF For AJAX的網站後,在本機運作正常,部署到客戶端時,如果連結service.svc發生404的錯誤時,可能是伺服器尚未設定*.svc的處理常式對應
(發生的原因可能是:先安裝WCF再安裝IIS)

二、解決方案:
  A、開啟網際網路資訊服務 (IIS) MMC 嵌入式管理單元
  B、進入處理常式對應,檢查下圖中*.svc的對應設定


 
C、如果沒有上圖中的*.svc對應,就必須手動完成設定,以4.0和64位元作業系統為例:
    1、先設定svc-Integrated-4.0,點選 [新增 Managed 處理常式]
 

要求路徑:*.svc
    類型(T):System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    名稱(N):svc-Integrated-4.0
    並點選『要求限制』按鈕,取消核取方塊,並點選『確定』完成設定1。

   2、設定svc-ISAPI-4.0_64bit,點選[新增指令碼對應]
 

要求路徑:*.svc
    執行檔(E):%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll
    名稱(N):svc-ISAPI-4.0_64bit
    並點選『要求限制』按鈕,取消核取方塊,並點選『確定』完成設定2。

  D、完成上述的設定後,就可以讓.NETFramework4.0的web應用程式,支援WCF的服務。

三、後記:
  以上說明,希望此備忘錄能幫助使用WCF服務遇到困境的程式開發者解決問題。

32位元4.0的類型:System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
32位元4.0的執行檔:%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll