BloggerAds

2011年8月29日 星期一

ASP.NET的WebService + autocomplete + tagit 合體

在使用Google+、Facebook時,會常常看到Tag這個東西,這東西在使用上,很方便,而且長的還蠻好看的,我很喜歡這操作很直覺的東西,所以上網找了些plugin,並拿來實作,而我找了 tagit 這個plugin,還算簡單使用(而且我認為這是我找的 plugin 當中最漂亮的...)。


一般的使用很簡單,照著 tagit 的 example就可以用了,但是一般的tag通常都會加上自動完成(AutoComplete)功能,所以不加個AutoComplete感覺就很弱,下面就提供個範例是用C#的WebService來實作AutoComplete功能(PHP很簡單,下面會提到一點):


1.在WebService部份,我們用DataTable來傳回傳,所以可以在asmx.cs這樣寫:
[WebMethod]
public DataTable GetList(string prefixText) {  
        DataTable dt = new DataTable();
        //從資料庫查詢資料的語法,請自發揮...     
        // ......略
        return dt;    //最後return一個DataTable
}
2.在aspx部份,用一個TextBox:
<asp:TextBox ID="txtTag"  runat="server" autocomplete="off"  />
3.再來就是JavaScript的實作了,通常是在document.ready時實作
$(document).ready(function() {
    $("#<% =txtTag.ClientID %>").tagit({
        allowSpaces: true,
        tagSource: function(request, response) {
            $.ajax({
                url: "/GetList.asmx/GetList", //步驟1的WebService網址及Function名稱
                data: { prefixText: request.term }, //要傳入WebService Function的變數,這裡是用來抓user所輸入的內容
                dataType: "xml",  //dataType設成Xml,php直接用json,再搭配json_encode來產生資料就可以了
                type: "POST",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",    //這裡很重要,要把contentType改成WebService預設回傳的application/x-www-form-urlencoded
                dataFilter: function(data) { return data; },
                success: function(data) {    //成功抓到資料後,要執行的動作
                    response($.map($(data).find("[欄位名稱]"), function(item) {  //因為是XML所以用這個方式來取資料,[欄位名稱]請記得更改成DataTable的欄位名稱
                        return { value: $(item).text() }
                    }));
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus + ":" + errorThrown);  //Debug用
                }
            });
        }         
    });
4.AutoComplete的部份完成!


5.如果要再龜毛點,限制使用者必須輸入DataTable中的內容的話,就在JavaScript中先加入這一段:
$.expr[':'].textEquals = function(a, i, m) {
        return $(a).text().match("^" + m[3] + "$");
};
6.再來改一下document.ready中tagit的部份,加入onTagAdded 的事件。


7.最後還要為tagit所產生的text加入change事件。


6+7後的JavaScript如下:
$(document).ready(function() {
    $("#<%=txtTag.ClientID %>").tagit({
        allowSpaces: true,
        tagSource: function(request, response) {
            $.ajax({
                url: "/GetList.asmx/GetList",
                data: { prefixText: request.term },
                dataType: "xml",
                type: "POST",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                dataFilter: function(data) { return data; },
                success: function(data) {
                    response($.map($(data).find("[欄位名稱]"), function(item) {
                        return { value: $(item).text() }
                    }));
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus + ":" + errorThrown);
                }
            });
        },
        onTagAdded: function(event, tag) {  
            //注意!別在這alert東西,不然會執行兩次
            //.ui-autocomplete、tagit-label 是tagit執行後預設的class
            if ($(".ui-autocomplete li:textEquals('" + tag.find(".tagit-label").text() + "')").size() == 0) {
                that.removeTag(tag);    //若輸入的內容不在資料庫中,則移除tag
            }
        }
    });


    $(".tagit input").change(function() {
        if ($(".tagit li:textEquals('" + $(this).val() + "')").size() == 0) {
            $(this).val('');  //若輸入的內容不在資料庫中,則清空TextBox的內容
        }
    });
});
8. 再次大功告成


參考資料:
http://stackoverflow.com/questions/2587378/how-to-implement-mustmatch-and-selectfirst-in-jquery-ui-autocomplete
https://github.com/aehlke/tag-it
http://jqueryui.com/demos/autocomplete/

UserControl 提供事件給網頁(Parent Page)觸發的方式

最近在弄一個讓 UserControl 提供事件給網頁呼叫的東西下面就提供一個範例,來讓UserControl中的 GridView的 RowSelecting 事件提供給網頁(Parent Page)觸發

1.首先,在UserControl的ascx.cs中,宣告一個事件:
public event EventHandler PublicRowSelecting;
2.再來還是在UserControl的ascx.cs中,讓原本的GridView RowSelecting的事件,執行剛剛宣告的事件PublicRowSelecting:
protected void gvMain_RowSelecting(object sender, GridViewSelectEventArgs e) {                             
            this.PublicRowSelecting(this, new EventArgs());       
}
3.接下來就是在網頁中使用了,在網頁(Parent Page)的aspx.cs 直接設定事件
UserControl1.PublicRowSelecting += new EventHandler(UserControl1_PublicRowSelecting);
4. UserControl1_PublicRowSelecting 是你要執行的程式,這個範例只要 Response.Write就好了

protected void UserControl1_PublicRowSelecting(object sender, EventArgs e) {
      Response.Write("Test OK");
}
5.大功告成,接下來只要執行到 UserControl中GridView的RowSelecting事件,就會執行UserControl1_PublicRowSelecting了。

2011年8月23日 星期二

.Net Web Service Internal Server Error 錯誤處理方式


在.Net 使用Web Service的方式很簡單,只要使用下列code就可以使用

首先在aspx加上如下程式:
<asp:ScriptManager runat="server" ID="ScriptManager1">
    <Services>
        <asp:ServiceReference Path="~/AAA.asmx" />
    </Services>
</asp:ScriptManager>
JavaScript即可用下列方式使用:
Class名稱.function名稱(參數, 完成時執行的function名稱, 錯誤時執行的function名稱, TimeOut時執行的function名稱);
ex.
AAA.funAAA(strB, OnComplete, OnError, OnTimeOut)

但若出現「Internal Server Error」,往往會讓人摸不著頭緒,很難找原因。在這提供幾個參考的debug方式:

1.先檢查程式中Web Service的路徑(URL)是否有錯誤,相對路徑與絕對路徑的使用是否都抓到asmx檔案。

2.Web Service是否有正確回傳資料,可直接打上網址 (ex. http://localhost/AAA.asmx) 並直接輸入參數檢查資料是否正確,或是否有錯誤發生。

3.若WebService 無法用遠端存取,只可在本機(Local)存取 ,則要在web.config加上下列藍色的部份:
<configuration>
    <system.web>
        <webServices>
            <protocols>
                <add name="HttpPost"/>
                <add name="HttpGet"/>
            </protocols>
        </webServices>

    </system.web>
</configuration>

2011年8月16日 星期二

ASP.NET Page Life Cycle 圖

最近在找一些有關ASP.NET Page的 Life Cycle的資料,看到了這張MSDN提供的圖(應該是Lag了很久...),覺得這張圖表達的很清楚,所以貼上來,當作自已的備忘錄,參考看看。


轉載資料:http://blogs.msdn.com/b/aspnetue/archive/2010/01/14/asp-net-page-life-cycle-diagram.aspx