BloggerAds

顯示具有 C# 標籤的文章。 顯示所有文章
顯示具有 C# 標籤的文章。 顯示所有文章

2012年1月18日 星期三

(Chrome、FireFox) JavaScript設定值給TextBox時,無法觸發PostBack的一種解法


如果有使用.NET 中TextBox的OnTextChanged事件,希望在TextBox的文字變動後,在Server端做一些事,通常會像下方這樣用:
ex. <asp:TextBox ID="txt1" runat="server" OnTextChanged="txt1_TextChanged" AutoPostBack="True" />

這個方式在人為操作的狀況下並不會有什麼問題,修改TextBox中的字後,會PostBack去執行程式。但如果修改TextBox中的文字,是使用JavaScript去設定值的話(ex. txt1.value = 'abc'),在各瀏覽器卻會有不同的結果產生,IE 會正常的執行 PostBack,但在Chrome、FireFox卻無法正常的觸發PostBack!

在試過jQuery的一些function後(ex. bind、on、trigger),發現還是沒辦法解決這個問題,最後只好用一個偏方來處理,使用setInterval一段時間就檢查一次TextBox的值,發現值有變動,就執行PostBack,解法如下:

$(document).ready(function() {          
    //非IE才設Interval,因為IE可正常觸發
    if(navigator.userAgent.indexOf("MSIE")==-1) {
        setInterval('detectValueChange();', 500);
    }
});
   
function detectValueChange() {
    currentValue = $('#<%=txt1.ClientID%>').val();
    oldValue = $('#<%=hid1.ClientID%>').val();
         
    if (currentValue != oldValue) {
        //使用<asp:HiddenField>暫存值,讓PostBack後,值還存在 
        $('#<%= hid1.ClientID%>').val(currentValue);
        __doPostBack('<%= txt1.ClientID%>', '');              
    }  
}       

2011年11月9日 星期三

[C#]在有驗證控制項的狀態下幫Button加上confirm (OnClientClick +Validator)


如果要對一個asp:Button控制項做再次詢問的動作(ex. 確認是否刪除? ),一般來說是可以直接這樣用:


<asp:Button ID="btnSubmit" runat="server" Text="OK" onclick="btnSubmit_Click"
    CausesValidation="true" OnClientClick="return confirm('are you sure?');"/>


而在有驗證控制項的狀況下,若還是用上面的return confirm方法,可是會讓驗證控制項失效的,所以要改成下列這種用法:

<asp:Button ID="btnSubmit" runat="server" Text="OK" onclick="btnSubmit_Click"
    CausesValidation="true" OnClientClick="if (Page_ClientValidate('[驗證群組]')) { return confirm('are you sure?');}"/>

其中 [驗證群組] 要記得改成你所設定的 ValidationGroup 

2011年11月1日 星期二

Google Analytics API called by C#

這是可以透過Google Analytics API 去抓出你網站的拜訪資料的功能,主要是送一個Request,再接收XML檔案,下面分兩段說明,首先是抓回XML的部份,:
(以下內容是參考 http://www.dotblogs.com.tw/lastsecret/archive/2010/10/06/18157.aspx )
private void GetXml() {  
        //送出request的網址
        var request = (HttpWebRequest)HttpWebRequest.Create(
            //在這是取國家的訪客數,參數可參考http://code.google.com/intl/zh-TW/apis/analytics/docs/gdata/gdataReferenceDataFeed.html#maxResults
            string.Format("https://www.google.com/analytics/feeds/data?"+                        
                            "ids=ga%3A{0}&dimensions=ga%3Acountry" +
                            "&metrics=ga%3Avisits&" +
                            "start-date={1}&end-date={2}&sort=-ga%3Avisits&max-results=10",
                            "12345678",  //Google Analytics 網站的ID
                            "2011-09-24",
                            DateTime.Now.ToString("yyyy-MM-dd")));

        //在header必須帶入token,token的取得請看下方的方法
        request.Headers.Add("Authorization", "GoogleLogin auth=" + GetAuthToken());

        try {
            var response = request.GetResponse();

            var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();

            //抓到XML, 存到暫存資料夾
            StreamWriter rd = File.CreateText(Server.MapPath("~/TempFile") + @"\Analytics_Country.xml");
            rd.Write(responseContent);
            rd.Flush();
        } catch (Exception ex) {
            Javascript.Alert(this.Page, "Error:" + ex.ToString());
        }
}

private static string GetAuthToken() {
        var postContent = string.Format(@"accountType=GOOGLE&Email={0}&Passwd={1}&service=analytics&source={2}",
                                         "Account", //Google 同號
                                         "PWD", //Google 密碼
                                         "1234"//隨便
                                        );

        byte[] bPostData = Encoding.ASCII.GetBytes(postContent);

        //參數與用法
        //參考http://code.google.com/intl/zh-TW/apis/accounts/docs/AuthForInstalledApps.html
        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://www.google.com/accounts/ClientLogin");
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = bPostData.Length;

        var reqStream = new StreamWriter(req.GetRequestStream());

        reqStream.Write(postContent);
        reqStream.Flush();

        HttpWebResponse rep = (HttpWebResponse)req.GetResponse();
        StreamReader repStream = new StreamReader(rep.GetResponseStream(), Encoding.UTF8);
        string ctx = repStream.ReadToEnd();

        //送出的response抓取token的值
        return Regex.Split(ctx, "Auth=", RegexOptions.IgnoreCase)[1];
     
    }  
再來是抓XML中的資料:
(以下內容是參考http://www.reimers.dk/jacob-reimers-blog/added-google-analytics-reader-for-net)
protected void GetData(object sender, EventArgs e) {
        //讀XML檔案
        XDocument xmlDoc = XDocument.Load(Server.MapPath("~/TempFile") + "/Analytics_Country.xml");
        XNamespace defaultSpace = xmlDoc.Root.GetDefaultNamespace();
        XNamespace dxpSpace = xmlDoc.Root.GetNamespaceOfPrefix("dxp");
     
        //LINQ  XML    
        var datas = from entry in xmlDoc.Root.Descendants(defaultSpace + "entry")
                    select new {
                        Country = entry.Element(dxpSpace + "dimension").Attribute("value").Value,
                        Value = entry.Element(dxpSpace + "metric").Attribute("value").Value
                    };
     
        foreach (var entry in datas) {          
            Response.Write("Country:" + entry.Country);
            Response.Write("Visits: " + entry.Value + "<br />");
        }
        //datas.ToDictionary<string, int>(m => m.Country, m => m.Value);
    }

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

2011年7月27日 星期三

C#將DataTable做Group By並取SUM、AVG、COUNT的方法(不用LINQ)

LINQ是個很方便的東西,但在比較舊的環境(.Net Framerwork 3.0以下的版本),是沒辦法使用LINQ的,這時要將DataTable做Group By可是很麻煩的一件事,下面就提供範例:
DataTable dt = new DataTable();    //原來的資料
dt = Get(); //取得資料,PS. Get()是我自己寫的Function,要記得換成你取得DataTable的function

//將原來的DataTable做Distinct並複製到新DataTable,ToTable的第一個參數是設定是否
//要做Distinct,當然要設成true,其他參數是要做Group By的欄位名稱
DataTable dtGroup = dt.DefaultView.ToTable(true, "column1", "column2");

//開始加欄位
dtGroup.Columns.Add("CountColumn");
dtGroup.Columns.Add("SumColumn");
dtGroup.Columns.Add("AvgColumn");

int count = 0;

for (int i = 0; i < dtGroup.Rows.Count;i++) {
    //取資料,用String是因為上方加欄位時,沒指定型別為數字
    string strCount = dt.Select("column1='" + dtGroup.Rows[i]["column1"].ToString() + "'").Length.ToString();
    string strSum = dt.Compute("SUM(column3)", "column1='" + dtGroup.Rows[i]["column1"].ToString() + "'").ToString();
    string strAvg = dt.Compute("AVG(column4)", "column1='" + dtGroup.Rows[i]["column1"].ToString() + "'").ToString();

    //設定資料
    dtGroup.Rows[i]["CountColumn"] = (strCount == "" ? "0" : strCount);
    dtGroup.Rows[i]["SumColumn"] = (strSum == "" ? "0" : strSum);
    dtGroup.Rows[i]["AvgColumn"] = (strAvg  == "" ? "0" : strAvg );       
}
最後dtGroup就是Group By後的資料了。

用jQuery取得RadioButtonList所選的值

開發.NET程式時,常常會使用到RadioButtonList控制項,在很多狀況下常需要依照使用者所選的值去做一些判斷或動作,雖然.Net本身就有OnSelectedIndexChanged事件可以用,搭配UpdatePanel等,可以做到不用PostBack的功能,但用jQuery也是可以寫的很簡單。

若使用的是RadioButtonList控制項,aspx內容如下:

<asp:RadioButtonList ID="rblTest" runat="server" >
    <asp:ListItem Text="1" Value="1" Selected="True" />
    <asp:ListItem Text="2" Value="2" />           
</asp:RadioButtonList>
產生的Html語法會長成這個樣子:
<table id="rblTest" border="0">
<tr>
<td><input id="rblTest_0" type="radio" name="rblTest" value="1" checked="checked" /><label for="rblTest_0">1</label></td>
</tr><tr>
<td><input id="rblTest_1" type="radio" name="rblTest" value="2" /><label for="rblTest_1">2</label></td>
</tr>
</table>
有看到吧? 產生的input物件,name 都是 rbTest,但id卻是以rbTest_開頭,再加上從0開始的序號,所以如果要使用jQuery取得所選的值的話,可以有兩種方法:
1.用id開頭取得:
$("input[id^='<% =rblTest.ClientID %>']:checked").val()
2.用name取得:
$("input[name='<% =rblTest.ClientID %>']:checked").val()
兩種都可以試試。

2011年7月15日 星期五

當 $(document).ready 碰上UpdatePanel

在 ASP.NET的開發中,UpdatePanel 是一個讓人又愛又恨的存在,讓人很方便使用,卻又常會造成一些問題。其中一個問題就是當UpdatePanel的(Partial) PostBack觸發後,你會發現你在$(document).ready中所設定的事件、屬性、ccs…等,全部都消失了,畫面並沒有reload,但你設定的動畫、mouseover、mouseout、watermark…等,卻都失效,沒有作用了。下面就是為了應對這種問題的解決方式:
$(document).ready(function() {
     pageLoad();
   
     Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function() {
            pageLoad();
     });
});

function pageLoad() {
    //你要執行的程式碼
}
加入Sys.WebForms.PageRequestManager.getInstance().add_endRequest 這個事件,並重新執行一次原本$(document).ready所執行的程式就可以解決這個問題了。

如果你要在UpdatePanel的(Partial) PostBack執行前,去處理一些事件,像是記錄當下的數值之類的,你可以用 Sys.WebForms.PageRequestManager.getInstance().add_beginRequest這個事件來做處理。

如果你在$(document).ready中有設定css的class,這個方式在Chrome、Firefox等瀏覽器下,也可以確實的解決問題。但在IE下,有時你會發現,不管你怎麼重新設定css class,好像都沒作用,javascript事件、function、甚至用$(selector).css()來設定css,全部都有跑,但唯獨設定css class的部份卻跟沒跑一樣。

如果你的css class是寫在網頁中,那這個問題的解決方式有二:
1.將你的css屬性,全改用$(selector).css()來設定。
2.將你class的style區段移至<head>中,這樣就可以解決問題了,真是莫明奇妙...

參考資料:
http://stackoverflow.com/questions/256195/jquery-document-ready-and-updatepanels
http://stackoverflow.com/questions/1732164/losing-css-class-added-through-jquery-on-updatepanel-partial-postback
http://sudheerkondraguntaprogramming.blogspot.com/2011/05/issue-with-css-stylesheet-and.html

2011年7月1日 星期五

jQuery UI Modal Dialog 中ASP:Button 無法PostBack的解決方式

如果有在.NET網頁(aspx)中使用jQuery UI 的Modal Dialog Plugin的人,應該會發現,若將ASP:Button控制項放在Dialog中,裡面的Button按下去是不會PostBack的,google了一下後,發現只要加一行程式就可以解決了,解決方式如下:
$("#btnA").click(function() {                             
    $("#divDialog").dialog({    //顯示Modal Dialog
        title: 'title',
        modal: true
    });
    //重點在這
    $("#divDialog").parent().appendTo($("form:first")); 
});          

$("#btnCancel").click(function() {
    $("#divDialog").dialog("close");   //關閉Modal Dialog
});

參考資料:
http://stackoverflow.com/questions/568784/jquery-modal-form-dialog-postback-problems

2011年6月22日 星期三

ASP.NET 動態新增Control、UserControl在PostBack後的處理

當有控制項(Control)或使用者控制項(UserControl)在頁面中是屬於動態新增的,若在頁面上不會觸發PostBack事件,其實是很好處理的,在使用上不會有什麼大問題。問題在於觸發PostBack的情況是很容易發生的,當PostBack發生後,你會發現所有動態產生的控制項通通不見了,這個問題實在是很惱人,所以在動態新增控制項時,要做一些特別的處理,程式才會乖乖的照著你的意思跑。

動態增加控制項的方法如下(以下以使用者控制項為例):
//載入User Control
UserControl1 ucObj=(UserControl1)LoadControl("~/UserControl1.ascx");

//若為一般控制項(Control),只要new一個新物件即可
//以TextBox為例,TextBox txtObj = new TextBox();

panel1.Controls.Add(ucObj); //加在Panel中
若上述程式放在按鈕的Click事件中,當User每按一次按鈕時,控制項照理說會一直增加,但實際上卻一直只有一個UserControl出現在畫面上。出了什麼問題? 原因就是沒有ViewState,所以PostBack後,原先增加的控制項就消失了,只有最後新增的一個控制項存在。因為是動態新增的,所以在Page_Init時.NET沒辦法將控制項重建,而解決方式就是用ViewState或Session將新增的控制項總數記下來,在Page_Load時將動態新增的控制項加回去,在新增控制項時,要多記錄控制項數目,所以上面的程式要改成如下:
//載入User Control
UserControl1 ucObj=(UserControl1)LoadControl("~/UserControl1.ascx");

panel1.Controls.Add(ucObj); //加在Panel中

if (ViewState["UcCount"] != null) {
    //記錄控制項數目
    ViewState["UcCount"]=           (int.Parse(ViewState["UcCount"].ToString())+1).ToString();
}else{
    ViewState.Add("UcCount", "1");
}
另外,在Page_Load事件中,要加入下列程式碼:
if (ViewState["UcCount"] != null) {
    for (int i = 1; i <= int.Parse(ViewState["UcCount"].ToString()); i++) {                              panel1.Controls.Add((UserControl1)LoadControl("~/UserControl1.ascx"));
    }
}
另外要注意的是,新增控制項時不可以設定ID(ex. ucObj.ID = "xxx"),否則每次PostBack時,都會視為一個新的物件,而讓PostBack前輸入的值消失。

參考資料:
http://social.msdn.microsoft.com/forums/zh-TW/236/thread/c18da009-fbcd-437b-9f9c-f758ade1e477/

2011年6月20日 星期一

ASP.NET錯誤:具有潛在危險 Request.Form 的值已從用戶端 偵測到 對應方式

在ASP.NET中,預設會將XSS (Cross Site Script)攻擊擋掉,若發現XSS攻擊,ASP.NET就會出現下列這種錯誤訊息:
具有潛在危險 Request.Form 的值已從用戶端 (XXXX) 偵測到
對於網頁開發者來說,自動擋掉錯誤是一件好事,但系統卻會出現錯給你的User看,這是個很不好的,為了避免這種狀況,
有一種解決方式是將 validateRequest 設成false,如果是針對個別網頁的話,修改的地方如下:
<%@ Page Language="C#" AutoEventWireup="false" CodeFile="Test.aspx.cs" Inherits="Test" validateRequest="False" %>
如果要針對整個網站的話,則是透過修改 web.config來達到整個網站關閉的目的
<system.web>
         <pages validateRequest="False" />
</system.web>

但若依上述方式修改,等於是讓系統開了個漏洞,所以若以上述方式修改的話,還必須要為每個控制項的值加入HtmlEncode,以防止XSS攻擊,ex.
txtBox1.Text = HttpUtility.HtmlEncode(txtBox1.Text)
總而言之,上面的方式,我個人覺得不太好,所以接下來還有另一種方式:透過Error事件,來做處理。這也有兩種方式可以實作
第一種方式,是用Page_Error來做處理,在程式中加入如下程式:
    protected void Page_Error(object sender, EventArgs e) {              
        if (Server.GetLastError().GetType().ToString() == "System.Web.HttpRequestValidationException") {
            Response.Redirect([要導入的錯誤畫面]);
        }

        Server.ClearError(); //清掉錯誤,讓ASP.NET的錯誤不出現
    }
若嫌要在每個網頁加上這段程式很麻煩,可以建立一個 BasePage 類別,再讓每個網頁繼承即可。

另外還有一種更方便的方式:在 Global.asax新增application_error事件,程式如下:
 void Application_Error(Object sender, EventArgs e)
    {
       if (Server.GetLastError().GetType().ToString() == "System.Web.HttpRequestValidationException") {
            Response.Redirect([要導入的錯誤畫面]);
        }
     
        Server.ClearError();
    }
這樣就不會出現ASP.NET錯誤了

參考資料:
http://tgw1029.blogspot.com/2010/02/requestform.html
http://social.msdn.microsoft.com/forums/zh-TW/236/thread/a4ecbacc-ffb9-49b9-bf52-93749a3e699a
http://www.dotblogs.com.tw/kirkchen/archive/2009/12/07/12314.aspx

2011年5月22日 星期日

XSL中轉換產出格式的方法

使用XSL來轉XML時,若要在XSL中轉換產出值的格式,有下列幾種方式:
一、可使用一些內建的函式來做轉換 (但內建的函式實在是很少...):
<x:value-of select="format-number([節點名稱], '###,###')"/>
則會將數字的資料轉為如 123,456 這種格式

二、自已寫XSL的function來做轉換

三、寫Script來做轉換,這個方式可以做到的功能就很多了,看是要用JavaScript、C#、VB...都可以,下列的例子是用來做日期轉換的函式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl [前置詞]" extension-element-prefixes="msxsl" xmlns:[前置詞]="urn:[前置詞]">

若是用Visual Studio 2008產生的XSL檔案的話,要在上面這段加入下面兩段文字
1. xmlns:[前置詞]="urn:[前置詞]"
2. exclude-result-prefixes="msxsl [前置詞]"

[前置詞] 是由自已隨便輸入的,但在使用時要注意全部都要相同。接下來再加入下列程式碼(範例):
<msxsl:script implements-prefix="[前置詞 ]" language="C#">
    <![CDATA[
      public string FormatDateTime(string xsdDateTime, string format) {
          DateTime date = DateTime.Parse(xsdDateTime);
          return date.ToString(format);
      }
    ]]>
</msxsl:script>

最後在使用時,直接像下面程式般呼叫函式,即可做到相當多的功能。
<xsl:value-of select="[前置詞 ]:FormatDateTime([節點名稱], 'yyyy MM DD')"/>

參考:
http://stackoverflow.com/questions/500915/format-a-date-in-xml-via-xslt
http://stackoverflow.com/questions/669291/xslt-decimal-formatting-based-on-input-xml
http://www.w3schools.com/xsl/

2011年5月19日 星期四

規則運算式(正規表示式)語法整理

以下為參考 Wiki 後,修改成自已比較能了解的規則運算式符號整理:

以下資料仍有一些不太了解或不知道該如何解釋的地方,請見諒。
編號字元描述
1\特殊字元的前置符號,將下一個字元標記為一個特殊字元。例如,「\n」代表換行符號。「\\」代表「\」而「\(」則代表「(」。
2^表示字串必須以後面的字元開頭。ex. ^aa,表示必須以aa開頭。
3$表示字串必須以後面的字元結尾。ex. aa$,表示必須以aa結尾。
4*表示 * 前面的字元可出現或不出現。例如:Gooo*gle 能匹配 Google、Goooooogle。* 等於 {0,}。
5+表示 + 前面的字元至少要出現一次(可出現多次),ex.go+gle 表示這個字串可以為gogle、google、gooooogle...。+ 等於 {1,}
6?表示 ? 前面的字元最多只可以出現一次(可不出現)。ex.colou?r 表示這個字串可以為color或colour。? 等於 {0,1}
7{n}大括號「{}」中包起來的數字n是一個非負整數。代表前面的字元一定要出現n次。例如:o{3} 可以為 Gooogle 的 ooo,但不能匹配 Google。
8{n,}大括號「{}」中包起來的數字n是一個非負整數。代表前面的字元至少要出現n次。ex.go{2,}gle 可以為google、goooogle,但gogle就不合格。
9{n,m}大括號「{}」中包起來的數字n是一個非負整數。代表前面的字元至少要出現n次,最多不可超過m次。n要小於等於m。ex. go{2,4}gle可以為google、goooogle,但gogle、gooooogle就不合格。
10?當?字元放在次數限制符號(*,+,?,{n},{n,},{n,m})後時,表示要不貪心的尋找,可增加效能。不貪心表示只要找到一個就好,不再找別的。
參考:http://deer.nublog.cc/article.php?i=20080225
11.表示除「\n」之外的任何字元。要表示包括「\n」在內的任何字元,請使用「[.\n]」。
12(pattern)小括號代表中間的pattern為一群組。
13(?:pattern)匹配pattern但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行儲存供以後使用。例如:run(?:n|ning) 能匹配 running 整個字串,並且從此字串後繼續比對。
13(?=pattern)正向預查,在任何匹配pattern的字串開始處匹配尋找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如:Office(?=2003|2007|2010) 能匹配 Office2003 中的 Office,但不能匹配 Office2005 中的 Office,而從 Office 字串後繼續比對。
14(?!pattern)負向預查,在任何不匹配pattern的字串開始處匹配尋找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如:Office(?!2003|2007|2010) 能匹配 Office2005 中的 Office,但不能匹配 Office2010 中的 Office,而從 Office 字串後繼續比對。
15x|y代表OR,ex. (A|a)pple 表示 這個字串可以為Apple或apple
16[xyz]代表可為中括號[]內的任一字元。ex.[abc]表示可為a、b、c任一字元。
17[^xyz]代表不可為中括號[]內的任一字元。ex.[abc]表示不可為a、b、c任一字元。
18[a-z]代表可為中括號[]內的字元區間內的任一字元。ex.[a-z]表示可為a~z間的任一字元。
19[^a-z]代表不可為中括號[]內的字元區間內的任一字元。ex.[a-z]表示不可為a~z間的任一字元。
20\b表示字和空白之間的交會點。ex.於aa bb aabb時,可以用 aa\b 找出 aa,而不會找出aabb、也不會找出「aa (空格)」。
21\B表示非字和空白之間的交會點
22\cx表示一個控制字元。例如,\cM匹配一個Control-M或Enter符。x的值必須為A-Z或a-z之一。否則會將c視為一個單純的「c」字元。
23\d可為任何數字。\d 等於[0-9]。
24\D不可為數字。\D 等於[^0-9]。
25\f換頁符號。\f 等於\x0c和\cL。
26\n換行符號。\n 等於\x0a和\cJ。
27\rEnter符號。\r 等於\x0d和\cM。
28\s代表任何空白字元,包括空格、製表符、換頁符等等。\s 等於[\f\n\r\t\v]。
29\S代表任何非空白字元。\S 等於[^\f\n\r\t\v]。
30\t代表Tab字元。\t 等於\x09和\cI。
31\v代表垂直Tab字元(Vertical Tab)。\v 等於\x0b和\cK。
32\w可為包括底線「_」的任何文字、數字。\w 等於「[A-Za-z0-9_]」。
33\W不可為包括底線「_」的任何文字、數字。。\W 等於「[^A-Za-z0-9_]」。
34\xn表示為n所代表的ASCII字元,n為十六進位值。十六進位值僅可寫兩個字元。例如,「\x41」匹配「A」。「\x041」則等價於「\x04&1」。
35\numnum是一個正整數。對前方括號內的字元做重複的動作。例如,「(.)\1」代表兩個連續的相同字元。
36\n標識一個八進制轉義值或一個向後參照。如果\n之前至少n個獲取的子運算式,則n為向後參照。否則,如果n為八進制數位(0-7),則n為一個八進制轉義值。
37\nm標識一個八進制轉義值或一個向後參照。如果\nm之前至少有nm個獲得子運算式,則nm為向後參照。如果\nm之前至少有n個獲取,則n為一個後跟文字m的向後參照。如果前面的條件都不滿足,若n和m均為八進制數位(0-7),則\nm將匹配八進制轉義值nm。
38\nml如果n為八進位數字(0-3),且m和l均為八進位數字(0-7),則代表八進位數字所代表的值。
39\unn是一個用四個十六進位數字表示的Unicode字元。代表n所表達的字元。例如,\u00A9代表版權符號(©)。
40\onn是一個用二個八進位數字表示的Unicode字元。代表n所表達的字元。例如,\o47。
參考資料:
http://deer.nublog.cc/article.php?i=20080225
http://ericbbs.blogspot.com/2009/08/2.html

2011年5月9日 星期一

Web.Config中 * 與 ? 的差別及順序

在Web.Config 中
<location path="dir1">
   <system.web>
     <authorization>       
       <deny users="?"/>
       <allow users="*"/>
    
     </authorization>
   </system.web>
</location>

其中
? = guest
* = everyone


這個例子的目的是「只讓有登入的人員可以存取這個目錄,未登入人員不可存取」,所以設定成不讓guest存取後,再讓everyone存取。
若順序相反成:
 <allow users="*"/>
 <deny users="?"/>

則系統判斷時,會因為一開始就允許everyone,而guest也屬於everyone,所以guest可以存取此資料夾,再下面的deny就等於沒作用了,會讓未登入的使用者也可以存取此資料夾,這點要注意!