2022年3月30日 星期三

[研究][ASP.NET]顯示IIS Session Time Out預設值設定時間

[研究][ASP.NET]顯示IIS Session Time Out預設值設定時間

2022-03-20

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#

目前為了安全性,各 Web Server 預設都有 Session TimeOut 機制,並且有各自的預設時間,依據Web Server 種類、版本可能都有所不同。

ASP.NET WebForm 網站 Web.config 可以設定 Session TimeOut 值 (不設也會有預設值)。

Session Time Out 在設定後是一個定值,Remaining Session Time 剩餘會話時間是指 Session 在 Time Out 前剩下的時間,是動態值。

Web.Config,例如設定為20分鐘。

<configuration>
   <system.web>
      <sessionState timeout="20"></sessionState>
   </system.web>
</configuration>

如果不知道,可以用程式測試看看

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server"></asp:Label><br />
            <asp:Label ID="Label2" runat="server"></asp:Label><br />
        </div>
    </form>
</body>
</html>


Default.aspx.cs

using System;
using System.Configuration;
using System.Web.Configuration;

namespace WebApplication1
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Configuration conf = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
            SessionStateSection section = (SessionStateSection)conf.GetSection("system.web/sessionState");
            int timeout = (int)section.Timeout.TotalMinutes;
            Label1.Text = timeout.ToString();

            System.Int64 timeout2 = System.Web.HttpContext.Current.Session.Timeout; // The time-out period, in minutes
            Label2.Text = timeout2.ToString();
        }
    }
}

測試出來 Windows Server 2019 + IIS Web Server + ASP.NET WebForm Web Application 網站的 Session TimeOut 預設值為 20 分鐘。

(完)

相關

sessionState 項目 (ASP.NET 設定結構描述) | Microsoft Docs
https://docs.microsoft.com/zh-tw/previous-versions/dotnet/netframework-3.0/h6bb9cz9(v=vs.85)

對談 (電腦科學) - 維基百科,自由的百科全書https://zh.wikipedia.org/wiki/%E4%BC%9A%E8%AF%9D_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)

HttpSessionState.Timeout 屬性 (System.Web.SessionState) | Microsoft Docs
https://docs.microsoft.com/zh-tw/dotnet/api/system.web.sessionstate.httpsessionstate.timeout?view=netframework-4.8


2022年3月23日 星期三

[研究]curl批次下載伏尼契手稿

[研究]curl批次下載伏尼契手稿

2022-03-23

簡體Windows上或許可以這樣下載 (下面命令同一行)

curl -o "#1.png" b.gmzm.org/2018/古代字画/伏尼契手稿/伏尼契手稿.VoynichManuscript.高清.耶鲁大学图书馆藏.约十五世纪_页面_[001-210].jpg


繁體MS-Windows上要這樣下載 (下面命令同一行)

curl -o "#1.png" http://b.gmzm.org/2018/%E5%8F%A4%E4%BB%A3%E5%AD%97%E7%94%BB/%E4%BC%8F%E5%B0%BC%E5%A5%91%E6%89%8B%E7%A8%BF/%E4%BC%8F%E5%B0%BC%E5%A5%91%E6%89%8B%E7%A8%BF.VoynichManuscript.%E9%AB%98%E6%B8%85.%E8%80%B6%E9%B2%81%E5%A4%A7%E5%AD%A6%E5%9B%BE%E4%B9%A6%E9%A6%86%E8%97%8F.%E7%BA%A6%E5%8D%81%E4%BA%94%E4%B8%96%E7%BA%AA_%E9%A1%B5%E9%9D%A2_[001-205].jpg

(完)

2022年3月21日 星期一

[研究][ASP.NET]錯誤: 無法取得未定義或 Null 參考的屬性 'setDefaults'

[研究][ASP.NET]錯誤: 無法取得未定義或 Null 參考的屬性 'setDefaults'

2022-03-20

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#



行: 18

錯誤: 無法取得未定義或 Null 參考的屬性 'setDefaults'

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

解決:搜尋整個方案,把 jQuery UI 的 1.12.1 改成 1.13.1。詳情請看

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'

(完)


2022年3月20日 星期日

[研究][ASP.NET]防跨站腳本攻擊(Cross-Site Scripting, XSS)之陣列化參數化查詢(Array Parameterized Query)

[研究][ASP.NET]防跨站腳本攻擊(Cross-Site Scripting, XSS)之陣列化參數化查詢(Array Parameterized Query)

2022-03-20

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#

為了避免 跨站腳本攻擊(Cross-Site Scripting, XSS),目前都會要求使用 參數化查詢(Parameterized Query)。

但對大量的 T-SQL 命令需求時,將一堆 SQL 命令(分號分隔)放在一個 SQL String 中 (組字串),在一次連線中送給 SQL Server 執行,是比較有效率的,因為連線的建立和中斷是耗時的。

另外要注意,.NET 一次送給 SQL Server 的 SQL String 長度有限制,所以依據 SQL 命令長度,可能 1000 條或更少,就要送出執行一次;最後不足1000條的要再執行一次。

(直接在 SQL Server Management Studio (SSMS) 中可以一次執行很長 SQL String 是兩碼子事情)

要同時考慮 參數化查詢、大量 SQL 命令、效率,就要把參數以陣列處理,以陣列化參數化查詢(或其他方法)。

Default.asp.cs

using System;
using System.Configuration;
using System.Data.SqlClient;

namespace WebApplication4
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string connectionString = ConfigurationManager.ConnectionStrings["TestDBConnectionString"].ConnectionString;
            string queryString = "";

            string[] paraName = new string[5];
            string[] paraValue = new string[5] { "1", "2", "3", "4", "5" };
            for (int i = 0; i < paraName.Length; i++)
            {
                //paraName[i] = "@FieldText[" + i.ToString() + "]";//別用陣列當名稱,會失敗
                paraName[i] = "@FieldText" + i.ToString() + "";
                queryString = queryString + "INSERT INTO [dbo].[Table1] ([FieldText]) VALUES(" + paraName[i] + ");";
            }
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlCommand command = new SqlCommand(queryString, connection);
                command.Parameters.Clear();
                for (int i = 0; i < paraName.Length; i++)
                    command.Parameters.AddWithValue(paraName[i], paraValue[i]);
                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }
    }
}

(完)

相關

使用參數化查詢搭配 SqlDataSource (C#) | Microsoft Docs
https://docs.microsoft.com/zh-tw/aspnet/web-forms/overview/data-access/accessing-the-database-directly-from-an-aspnet-page/using-parameterized-queries-with-the-sqldatasource-cs


2022年3月19日 星期六

[研究]DropDownList下拉選單的恩怨情仇(五)連動選單項目不存在的預選

 [研究]DropDownList下拉選單的恩怨情仇(五)連動選單項目不存在的預選

2022-3-19

環境:Visual Studio 2022 + ASP.NET + Web Application + WebForm + C#

續這篇

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。
https://shaurong.blogspot.com/2022/03/dropdownlistdropdownlist1-selectedvalue.html

[研究]DropDownList下拉選單的恩怨情仇(二)使用料庫儲存選項清單http://shaurong.blogspot.com/2022/03/dropdownlist.html

[研究]DropDownList下拉選單的恩怨情仇(三)已儲存項目不再提供於資料庫選項名單
http://shaurong.blogspot.com/2022/03/dropdownlist_19.html

[研究]DropDownList下拉選單的恩怨情仇(四)項目不存在的預選https://shaurong.blogspot.com/2022/03/dropdownlist_15.html

(下圖)新版分類選項

(下圖)舊版購買結果歷史紀錄 (芭樂、蘿蔔已經不再目前上面選項中)

Default2.aspx 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default2.aspx.cs"
    Inherits="WebApplication3.Default2" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <asp:SqlDataSource ID="SqlDataSource_FruitVegeType" runat="server"
        ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
        SelectCommand="SELECT N'' AS FruitVegeType UNION SELECT DISTINCT FruitVegeType FROM [FruitVegeList]"></asp:SqlDataSource>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
        SelectCommand="SELECT * FROM [FruitVegeRecord] WHERE ([sn] = @sn)"
        UpdateCommand="UPDATE [FruitVegeRecord] SET [FVType] = @FVType, [FruitBuy] = @FruitBuy WHERE [sn] = @sn">
        <SelectParameters>
            <asp:QueryStringParameter Name="sn" QueryStringField="sn" Type="Int32" DefaultValue="1" />
        </SelectParameters>
        <UpdateParameters>
            <asp:Parameter Name="FVType" Type="String" />
            <asp:Parameter Name="FruitBuy" Type="String" />
            <asp:Parameter Name="sn" Type="Int32" />
        </UpdateParameters>
    </asp:SqlDataSource>

    <form id="form1" runat="server">
        <div>
            <asp:DetailsView ID="DetailsView1" runat="server" Height="50px"
                DefaultMode="Edit" Caption="編輯"
                AutoGenerateRows="False" DataKeyNames="sn"
                DataSourceID="SqlDataSource1">
                <Fields>
                    <asp:BoundField DataField="sn" HeaderText="sn" InsertVisible="False" ReadOnly="True" SortExpression="sn" />
                    <asp:TemplateField HeaderText="FVType" SortExpression="FVType">
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox_FVType" runat="server" Text='<%# Bind("FVType") %>' Visible="false"></asp:TextBox>
                            <asp:DropDownList ID="DropDownList_FruitVegeType" runat="server"
                                AutoPostBack="true" DataTextField="FruitVegeType"
                                DataValueField="FruitVegeType"
                                DataSourceID="SqlDataSource_FruitVegeType"
                                OnSelectedIndexChanged="DropDownList_FruitVegeType_SelectedIndexChanged">
                            </asp:DropDownList>
                            <asp:SqlDataSource ID="SqlDataSource_FruitVegeName" runat="server"
                                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                                SelectCommand="SELECT N'' AS FruitVegeName UNION (SELECT FruitVegeName FROM [FruitVegeList] WHERE ([FruitVegeType] = @FruitVegeType))">
                                <SelectParameters>
                                    <asp:ControlParameter ControlID="DropDownList_FruitVegeType" Name="FruitVegeType" ConvertEmptyStringToNull="false" PropertyName="SelectedValue" />
                                </SelectParameters>
                            </asp:SqlDataSource>
                        </EditItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="FruitBuy" SortExpression="FruitBuy">
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox_FruitBuy" runat="server" Text='<%# Bind("FruitBuy") %>' Visible="false"></asp:TextBox>
                            <asp:DropDownList ID="DropDownList_FruitVegeName" runat="server"
                                DataSourceID = "SqlDataSource_FruitVegeName"
                                AutoPostBack="true" DataTextField="FruitVegeName"
                                DataValueField="FruitVegeName"
                                OnSelectedIndexChanged="DropDownList_FruitVegeName_SelectedIndexChanged">
                                <asp:ListItem></asp:ListItem>
                            </asp:DropDownList>
                        </EditItemTemplate>
                    </asp:TemplateField>
                    <asp:CommandField ShowEditButton="True" />
                </Fields>
            </asp:DetailsView>
        </div>
    </form>
</body>
</html>

Default2.aspx.cs 中部分


using System;
using System.Web.UI.WebControls;

namespace WebApplication3
{
    public partial class Default2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void DropDownList_FruitVegeType_SelectedIndexChanged(object sender, EventArgs e)
        {
            TextBox TextBox_FVType = (TextBox)DetailsView1.FindControl("TextBox_FVType");
            DropDownList DropDownList_FruitVegeType = (DropDownList)DetailsView1.FindControl("DropDownList_FruitVegeType");
            TextBox_FVType.Text = DropDownList_FruitVegeType.SelectedValue;
        }
        protected void DropDownList_FruitVegeName_SelectedIndexChanged(object sender, EventArgs e)
        {
            TextBox TextBox_FruitBuy = (TextBox)DetailsView1.FindControl("TextBox_FruitBuy");
            DropDownList DropDownList_FruitVegeName = (DropDownList)DetailsView1.FindControl("DropDownList_FruitVegeName");
            TextBox_FruitBuy.Text = DropDownList_FruitVegeName.SelectedValue;
        }
    }
}

按下「編輯」按鈕後出現


(完)

[研究]DropDownList下拉選單的恩怨情仇(四)項目不存在的預選

 [研究]DropDownList下拉選單的恩怨情仇(四)項目不存在的預選

2022-3-19

環境:Visual Studio 2022 + ASP.NET + Web Application + WebForm + C#

續這篇

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。
https://shaurong.blogspot.com/2022/03/dropdownlistdropdownlist1-selectedvalue.html

[研究]DropDownList下拉選單的恩怨情仇(二)使用料庫儲存選項清單http://shaurong.blogspot.com/2022/03/dropdownlist.html

[研究]DropDownList下拉選單的恩怨情仇(三)已儲存項目不再提供於資料庫選項名單
http://shaurong.blogspot.com/2022/03/dropdownlist_19.html

之前下拉選單一定只出現第一項,改進一下;

若已存資料庫中項目不再存在,希望「編輯」畫面下拉選單預選空白;

若已存資料庫中項目存在,希望「編輯」畫面下拉選單預選該項目。

Default.aspx 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication3.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server"
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                DeleteCommand="DELETE FROM [FruitRecord] WHERE [sn] = @sn"
                InsertCommand="INSERT INTO [FruitRecord] ([FruitBuy]) VALUES (@FruitBuy)"
                SelectCommand="SELECT * FROM [FruitRecord]"
                UpdateCommand="UPDATE [FruitRecord] SET [FruitBuy] = @FruitBuy WHERE [sn] = @sn">
                <DeleteParameters>
                    <asp:Parameter Name="sn" Type="Int32" />
                </DeleteParameters>
                <InsertParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                </InsertParameters>
                <UpdateParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                    <asp:Parameter Name="sn" Type="Int32" />
                </UpdateParameters>
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
                AllowSorting="True" AutoGenerateColumns="False"
                DataKeyNames="sn" DataSourceID="SqlDataSource1" 
                OnRowDataBound="GridView1_RowDataBound" 
                >
                <Columns>
                    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
                    <asp:BoundField DataField="sn" HeaderText="sn" InsertVisible="False" ReadOnly="True" SortExpression="sn" />
                    <asp:TemplateField HeaderText="FruitBuy" SortExpression="FruitBuy">
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox_FruitBuy" runat="server" ReadOnly="true"
                                Text='<%# Bind("FruitBuy") %>'></asp:TextBox>
                            <asp:SqlDataSource ID="SqlDataSource_FruitName" runat="server"
                                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                                SelectCommand="SELECT * FROM [FruitList]"></asp:SqlDataSource>
                            <asp:DropDownList ID="DropDownList_FruitBuy" runat="server"
                                AutoPostBack="true"
                                DataSourceID="SqlDataSource_FruitName"
                                 AppendDataBoundItems="true"
                                DataTextField="FruitName" DataValueField="FruitName" 
                                OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
                                <asp:ListItem></asp:ListItem>
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label1" runat="server" Text='<%# Bind("FruitBuy") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>

</body>
</html>

Default.aspx.cs 中部分


using System;
using System.Web.UI.WebControls;

namespace WebApplication3
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var row = GridView1.Rows[GridView1.EditIndex];
            TextBox TextBox_FruitBuy = (TextBox)row.FindControl("TextBox_FruitBuy");
            DropDownList DropDownList_FruitBuy = (DropDownList)row.FindControl("DropDownList_FruitBuy");
            TextBox_FruitBuy.Text = DropDownList_FruitBuy.SelectedValue;
        }

        protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow 
                && e.Row.RowState == (DataControlRowState.Edit | DataControlRowState.Alternate))
            {
                if (e.Row.RowIndex == GridView1.EditIndex)
                {
                    TextBox TextBox_FruitBuy = (TextBox)e.Row.FindControl("TextBox_FruitBuy");
                    DropDownList DropDownList_FruitBuy = (DropDownList)e.Row.FindControl("DropDownList_FruitBuy");
                    if (DropDownList_FruitBuy.Items.Contains(new ListItem(TextBox_FruitBuy.Text)))
                    {
                        DropDownList_FruitBuy.SelectedValue = TextBox_FruitBuy.Text;
                    }
                    else
                    {
                        DropDownList_FruitBuy.SelectedValue = "";
                    }
                }
            }
        }
    }
}

按下「編輯」按鈕後出現

(下圖)芭樂不在下拉選單中,下拉選單預選空白


(下圖)香蕉在下拉選單中,下拉選單預選香蕉
這種情況下,可以設定 TextBox_FruitBuy 為Visible = "false" 隱藏掉 (因為有的需求方不想看到兩個控制項 (ASP.NET Control),或不想在該處看到 TextBox )

別忘了GridView1_RowUpdating()要檢查按下「更新」按鈕後,新值是否屬於新名單中選項。
甚至按下「取消」觸發的GridView1_RowCancelingEdit()也進行檢查。但也或許可以不用,看該欄位是否允許不選擇,也就是輸入空字串。

敝人遇過某種下拉選單,允許不選,選項有數千項,隨時增、減、改名,非敝人管理,也不會通知敝人,就合適這種情況。

(完)

[研究]DropDownList下拉選單的恩怨情仇(三)已儲存項目不再提供於資料庫選項名單

[研究]DropDownList下拉選單的恩怨情仇(三)已儲存項目不再提供於資料庫選項名單

2022-3-19

環境:Visual Studio 2022 + ASP.NET + Web Application + WebForm + C#

續這篇

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。
https://shaurong.blogspot.com/2022/03/dropdownlistdropdownlist1-selectedvalue.html

[研究]DropDownList下拉選單的恩怨情仇(二)使用料庫儲存選項清單http://shaurong.blogspot.com/2022/03/dropdownlist.html

Default.aspx 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication3.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server"
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                DeleteCommand="DELETE FROM [FruitRecord] WHERE [sn] = @sn"
                InsertCommand="INSERT INTO [FruitRecord] ([FruitBuy]) VALUES (@FruitBuy)"
                SelectCommand="SELECT * FROM [FruitRecord]"
                UpdateCommand="UPDATE [FruitRecord] SET [FruitBuy] = @FruitBuy WHERE [sn] = @sn">
                <DeleteParameters>
                    <asp:Parameter Name="sn" Type="Int32" />
                </DeleteParameters>
                <InsertParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                </InsertParameters>
                <UpdateParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                    <asp:Parameter Name="sn" Type="Int32" />
                </UpdateParameters>
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False"
                DataKeyNames="sn" DataSourceID="SqlDataSource1">
                <Columns>
                    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
                    <asp:BoundField DataField="sn" HeaderText="sn" InsertVisible="False" ReadOnly="True" SortExpression="sn" />
                    <asp:TemplateField HeaderText="FruitBuy" SortExpression="FruitBuy">
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox_FruitBuy" runat="server" ReadOnly="true"
                                Text='<%# Bind("FruitBuy") %>'></asp:TextBox>
                            <asp:SqlDataSource ID="SqlDataSource_FruitName" runat="server"
                                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                                SelectCommand="SELECT * FROM [FruitList]"></asp:SqlDataSource>
                            <asp:DropDownList ID="DropDownList_FruitBuy" runat="server"
                                AutoPostBack="true"
                                DataSourceID="SqlDataSource_FruitName"
                                DataTextField="FruitName" DataValueField="FruitName" 
                                OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label1" runat="server" Text='<%# Bind("FruitBuy") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>

</body>
</html>

Default.aspx.cs 中部分


protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    var row = GridView1.Rows[GridView1.EditIndex];
    TextBox TextBox_FruitBuy = (TextBox)row.FindControl("TextBox_FruitBuy");
    DropDownList DropDownList_FruitBuy = (DropDownList)row.FindControl("DropDownList_FruitBuy");
    TextBox_FruitBuy.Text = DropDownList_FruitBuy.SelectedValue;
}

按下「編輯」按鈕後出現

芭樂雖然不再於下拉選單提供,但不會再出現下面錯誤。
DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。

別忘了GridView1_RowUpdating()要檢查按下「更新」按鈕後,新值是否屬於新名單中選項。
甚至按下「取消」觸發的GridView1_RowCancelingEdit()也進行檢查。

(完)

[研究]DropDownList下拉選單的恩怨情仇(二)使用料庫儲存選項清單

[研究]DropDownList下拉選單的恩怨情仇(二)使用料庫儲存選項清單

2022-3-19

環境:Visual Studio 2022 + ASP.NET + Web Application + WebForm + C#

續這篇,之前下拉選項寫死程式中,若項目多,或需要該下拉選單的地方多,可把清單放存放於資料庫中,免得增減項目要到處改程式。

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。
https://shaurong.blogspot.com/2022/03/dropdownlistdropdownlist1-selectedvalue.html

Default.aspx 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication3.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server"
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                DeleteCommand="DELETE FROM [FruitRecord] WHERE [sn] = @sn"
                InsertCommand="INSERT INTO [FruitRecord] ([FruitBuy]) VALUES (@FruitBuy)"
                SelectCommand="SELECT * FROM [FruitRecord]"
                UpdateCommand="UPDATE [FruitRecord] SET [FruitBuy] = @FruitBuy WHERE [sn] = @sn">
                <DeleteParameters>
                    <asp:Parameter Name="sn" Type="Int32" />
                </DeleteParameters>
                <InsertParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                </InsertParameters>
                <UpdateParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                    <asp:Parameter Name="sn" Type="Int32" />
                </UpdateParameters>
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" 
                DataKeyNames="sn" DataSourceID="SqlDataSource1">
                <Columns>
                    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
                    <asp:BoundField DataField="sn" HeaderText="sn" InsertVisible="False" ReadOnly="True" SortExpression="sn" />
                    <asp:TemplateField HeaderText="FruitBuy" SortExpression="FruitBuy">
                        <EditItemTemplate>
                            <%--<asp:TextBox ID="TextBox1" runat="server" Text= <%# Bind("FruitBuy") %>'></asp:TextBox>--%>
                            <asp:SqlDataSource ID="SqlDataSource2" runat="server"
                                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>"
                                SelectCommand="SELECT * FROM [FruitList]"></asp:SqlDataSource>
                            <asp:DropDownList ID="DropDownList1" runat="server"
                                SelectedValue='<%# Bind("FruitBuy") %>'
                                DataSourceID="SqlDataSource2"
                                DataTextField="FruitName" DataValueField="FruitName">
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label1" runat="server" Text='<%# Bind("FruitBuy") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>


按下「編輯」按鈕後出現

(完)

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。

[研究]DropDownList下拉選單的恩怨情仇(一)'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。

2022-3-19

環境:Visual Studio 2022 + ASP.NET + Web Application + WebForm + C#

下拉選單是個好用的東西,可以省卻使用者自己輸入的麻煩,由其名稱很長的時候;也可以限制使用者只能選擇特定的輸入;但若日後選項因業務需求者產生變化,那就是麻煩的事情了。

(下圖)假設下拉選單有3個選項

(下圖)假設一筆購買紀錄 (省卻價格、購買者、日期、、、)

Default.aspx 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication3.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>" 
                DeleteCommand="DELETE FROM [FruitRecord] WHERE [sn] = @sn" 
                InsertCommand="INSERT INTO [FruitRecord] ([FruitBuy]) VALUES (@FruitBuy)" 
                SelectCommand="SELECT * FROM [FruitRecord]" 
                UpdateCommand="UPDATE [FruitRecord] SET [FruitBuy] = @FruitBuy WHERE [sn] = @sn">
                <DeleteParameters>
                    <asp:Parameter Name="sn" Type="Int32" />
                </DeleteParameters>
                <InsertParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                </InsertParameters>
                <UpdateParameters>
                    <asp:Parameter Name="FruitBuy" DefaultValue="" ConvertEmptyStringToNull="false" Type="String" />
                    <asp:Parameter Name="sn" Type="Int32" />
                </UpdateParameters>
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" 
                 DataKeyNames="sn" DataSourceID="SqlDataSource1">
                <Columns>
                    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
                    <asp:BoundField DataField="sn" HeaderText="sn" InsertVisible="False" ReadOnly="True" SortExpression="sn" />
                    <asp:TemplateField HeaderText="FruitBuy" SortExpression="FruitBuy">
                        <EditItemTemplate>
                            <%--<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FruitBuy") %>'></asp:TextBox>--%>
<asp:DropDownList ID="DropDownList1" runat="server" SelectedValue='<%# Bind("FruitBuy") %>'> <asp:ListItem>橘子</asp:ListItem> <asp:ListItem>香蕉</asp:ListItem> </asp:DropDownList> </EditItemTemplate> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("FruitBuy") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </div> </form> </body> </html>

如果下拉選項的項目少,或選單只用一次 (其他地方只是讀出值),選項可以寫死在程式中,不用放資料庫中。

(下圖)執行結果如下,資料庫中目前儲存的值是「香蕉」,是選單的其中一項,所以「編輯」功能不會有問題。

如果某天香蕉不再是選項,把 

<asp:ListItem>香蕉</asp:ListItem>

註解成

<%--<asp:ListItem>香蕉</asp:ListItem>--%>

執行後,按下「編輯」按鈕就會出錯。(「資料完整性」有問題,儲存的資料應該是選項之一才對,DropDownList選不到符合儲存值的選項)


'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。

參數名稱: value

例外狀況詳細資訊: System.ArgumentOutOfRangeException: 'DropDownList1' 擁有的 SelectedValue 無效,因為它不在項目清單中。

********************************************************************************

解決:

方法一:如果「香蕉」選項,不是不再提供,而是改名為「台灣香蕉」,那把資料庫已儲存資料也改名為台灣香蕉可解決。

方法二:「編輯」畫面不要用下拉選單,改用TextBox,怕使用者亂輸入,就在 GridView1_RowUpdating() 中檢查輸入值是否屬於新的選項之一。但若選項名稱很長、或容易出錯,用 TextBox 不方便。

方法三:「香蕉」選項在「編輯」畫面下拉選單不移除,但在 GridView1_RowUpdating() 中檢查輸入值是否屬於新的選項之一。

方法四:方法三若很多選項不再提供,如何區別呢?改寫成如下,Value是實際值,Text顯示文字

<asp:ListItem Value="香蕉" Text="香蕉(廢除)">香蕉</asp:ListItem>

方法五:「編輯」畫面同時用 TextBox 和 DropDownList,TextBox有Bind(),放目前資料庫抓出的值,DropDownList 不放 Bind(),旁邊加上一按鈕,按下時把 DropDownList 選的值,放到 TextBox 去。不用按鈕則 DropDownList 加上屬性 AutoPostBack="True" 。

沒有絕對的最佳方法,也應該還有其他方式,依各種情境、需求方可接受方式,進行選擇。

(完)

[研究][ASP.NET]jQuery 3.6.0 錯誤: 無法取得未定義或 Null 參考的屬性 'regional'

[研究][ASP.NET]jQuery 3.6.0 錯誤: 無法取得未定義或 Null 參考的屬性 'regional'

2022-03-19

錯誤: 無法取得未定義或 Null 參考的屬性 'regional'




jQuery.readyException = function( error ) {
	window.setTimeout( function() {
		throw error;
	} );
};


********************************************************************************
後來解決下面的問題後,本問題也解決了。

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'

(完)

[研究][C#] 空字串 string.Empty 和 "" 比較測試

[研究][C#] 空字串 string.Empty 和 "" 比較測試

2200-03-19

String.Empty 欄位 (System) | Microsoft Docs

https://docs.microsoft.com/zh-tw/dotnet/api/system.string.empty?view=net-6.0
表示空字串。 此欄位為唯讀。

what is the difference between String.Empty and "" ?
https://social.msdn.microsoft.com/Forums/en-US/9977e45f-c8c5-4a8f-9e02-12f74c1c4579/what-is-the-difference-between-stringempty-and-quotquot-?forum=csharplanguage


protected void Page_Load(object sender, EventArgs e)
{
    string str1 = "";
    string str2 = string.Empty;
    if (str1 == str2)
        Label1.Text = "Same";
    else
        Label1.Text = "Not Same";
    str1 = "test";
    str2 = "test";
}

結果 Same

(完)

[研究][ASP.NET]jQuery.UI.Combined.1.13.1 的 datepicker 與 jQuery 3.6.0 相容測試

[研究][ASP.NET][JavaScript]jQuery.UI.Combined.1.13.1 的 datepicker 與 jQuery 3.6.0 相容測試

2022-3-19

因為這篇,敝人想測試一下目前最新 jQuery UI 的 datepicker 和 jQuery 3.6.0 相容性

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'
https://shaurong.blogspot.com/2022/03/aspnetjquery-360-datepicker.html

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#

NuGet 安裝 jQuery.UI.Combined.1.13.1時,實際上會安裝 jQuery.2.0.0 和 jQuery.UI.Combined.1.13.1,然後再把 jQuery 2.0.0 升級到 jQuery 3.6.0

Default.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="Scripts/jquery-3.6.0.js"></script>
    <script src="Scripts/jquery-ui-1.13.1.js"></script>
    <link href="Content/themes/base/jquery-ui.css" rel="stylesheet" />
    <script> 
        $(function () {
            $(".date").datepicker();
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="TextBox1" runat="server" CssClass="date" AutoComplete="Off"></asp:TextBox>
        </div>
    </form>
</body>
</html>

測試結果



似乎正常。

********************************************************************************

測試

把     <script src="Scripts/jquery-ui-1.13.1.js"></script> 這行註解或砍掉,Chrome 99 上執行沒有跳出任何錯誤,只是日期不會顯示。

但是 Internet Explorer 11  ( IE11) 上顯示了錯誤。

錯誤: 物件沒有支援這個屬性或方法 'datepicker'


找到原因了,因該是之前升級 jQuery UI  時候,沒手動把
    <script src="Scripts/jquery-ui-1.12.1.js"></script>
都換成
    <script src="Scripts/jquery-ui-1.13.1.js"></script>
的原因

********************************************************************************

回到出事的方案,搜尋 jquery-ui-1.12.1.js 找不到,搜尋 jquery-ui 找到
App_Start\BundleConfig.cs 檔案


using System.Web.Optimization;
using System.Web.UI;

namespace PMSWeb
{
    public class BundleConfig
    {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkID=303951
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include(
                            "~/Scripts/WebForms/WebForms.js",
                            "~/Scripts/WebForms/WebUIValidation.js",
                            "~/Scripts/WebForms/MenuStandards.js",
                            "~/Scripts/WebForms/Focus.js",
                            "~/Scripts/WebForms/GridView.js",
                            "~/Scripts/WebForms/DetailsView.js",
                            "~/Scripts/WebForms/TreeView.js",
                            "~/Scripts/WebForms/WebParts.js"));

            // Order is very important for these files to work, they have explicit dependencies
            bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include(
                    "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js",
                    "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js",
                    "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js",
                    "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js"));

            // Use the Development version of Modernizr to develop with and learn from. Then, when you’re
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                            "~/Scripts/modernizr-*"));

            ScriptManager.ScriptResourceMapping.AddDefinition(
                "respond",
                new ScriptResourceDefinition
                {
                    Path = "~/Scripts/respond.min.js",
                    DebugPath = "~/Scripts/respond.js",
                });

            //string jquerystr = "3.5.1";
            string jquerystr = "3.6.0";
            ScriptManager.ScriptResourceMapping.AddDefinition("jquery", new ScriptResourceDefinition
            {
                Path = "~/Scripts/jquery-" + jquerystr + ".min.js",
                DebugPath = "~/Scripts/jquery-" + jquerystr + ".js",
                CdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-" + jquerystr + ".min.js",
                CdnDebugPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-" + jquerystr + ".js",
                CdnSupportsSecureConnection = false,
                LoadSuccessExpression = "window.jQuery"
            });

            string str = "1.12.1";
            ScriptManager.ScriptResourceMapping.AddDefinition("jquery.ui.combined", new ScriptResourceDefinition
            {
                Path = "~/Scripts/jquery-ui-" + str + ".min.js",
                DebugPath = "~/Scripts/jquery-ui-" + str + ".js",
                CdnPath = "http://ajax.aspnetcdn.com/ajax/jquery.ui/" + str + "/jquery-ui.min.js",
                CdnDebugPath = "http://ajax.aspnetcdn.com/ajax/jquery.ui/" + str + "/jquery-ui.js",
                CdnSupportsSecureConnection = false
            });

            string bootstrapversion = "3.3.6";
            ScriptManager.ScriptResourceMapping.AddDefinition("bootstrap", new ScriptResourceDefinition()
            {
                Path = "~/Scripts/bootstrap.min.js",
                DebugPath = "~/Scripts/bootstrap.js",
                CdnPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/" + bootstrapversion + "/bootstrap.min.js",
                CdnDebugPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/" + bootstrapversion + "/bootstrap.js",
                CdnSupportsSecureConnection = true,
                LoadSuccessExpression = "window.jQuery.fn.carousel"
            });
        }
    }
}

把 1.12.1 換成 1.13.1 即可。

(完)

相關

[研究]HTML5 的 input 標籤的 type 屬性的 日期、月曆測試
https://shaurong.blogspot.com/2022/04/html5-input-type_12.html

[研究]HTML5 的 input 標籤的 type 屬性的各種值
https://shaurong.blogspot.com/2022/04/html5-input-type.html

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'
https://shaurong.blogspot.com/2022/03/aspnetjquery-360-datepicker.html

[研究][ASP.NET][JavaScript]jQuery.UI.Combined.1.13.1 的 datepicker 與 jQuery 3.6.0 相容測試
https://shaurong.blogspot.com/2022/03/aspnetjqueryuicombined1131-datepicker.html

[研究][ASP.NET][JavaScript] jQuery datetimepicker 2.4.5 月曆套件試用(NuGet 安裝)
http://shaurong.blogspot.com/2018/03/javascript-jquery-date-and-time-picker.html

[研究][ASP.NET][JavaScript] Bootstrap V3 Datepicker 4.17.45 月曆 套件 安裝與試用
http://shaurong.blogspot.com/2018/03/bootstrap-v3-datepicker-41745.html

[研究][ASP.NET][JavaScript] Bootstrap Datepicker 1.7.1 月曆 套件 安裝與試用http://shaurong.blogspot.com/2018/03/bootstrap-datepicker-171.html

[研究][ASP.NET][JavaScript] jQuery UI v1.12.1 的 Datepicker 月曆 套件 安裝與試用http://shaurong.blogspot.com/2017/07/jquery-ui-datepicker.html

[jQuery] 月曆套件(一) @ 程式開發學習之路 :: 痞客邦 ::
http://pclevinblog.pixnet.net/blog/post/314562997-%5Bjquery%5D-%E6%9C%88%E6%9B%86%E5%A5%97%E4%BB%B6%28%E4%B8%80%29

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'

2022-03-19

錯誤: 物件沒有支援這個屬性或方法 'datepicker'




jQuery.readyException = function( error ) {
window.setTimeout( function() {
throw error;
} );
};


**********

原因參考這篇

[研究][ASP.NET]jQuery.UI.Combined.1.13.1 的 datepicker 與 jQuery 3.6.0 相容測試https://shaurong.blogspot.com/2022/03/aspnetjqueryuicombined1131-datepicker.html

(完)

相關

[研究]HTML5 的 input 標籤的 type 屬性的 日期、月曆測試
https://shaurong.blogspot.com/2022/04/html5-input-type_12.html

[研究]HTML5 的 input 標籤的 type 屬性的各種值
https://shaurong.blogspot.com/2022/04/html5-input-type.html

[研究][ASP.NET]jQuery 3.6.0 物件沒有支援這個屬性或方法 'datepicker'
https://shaurong.blogspot.com/2022/03/aspnetjquery-360-datepicker.html

[研究][ASP.NET][JavaScript]jQuery.UI.Combined.1.13.1 的 datepicker 與 jQuery 3.6.0 相容測試https://shaurong.blogspot.com/2022/03/aspnetjqueryuicombined1131-datepicker.html

[研究][JavaScript] jQuery Date and Time picker 2.4.5 (jquery-datetimepicker)(NuGet 安裝)
https://shaurong.blogspot.com/2018/03/javascript-jquery-date-and-time-picker.html

[研究][ASP.NET][JavaScript] Bootstrap V3 Datetimepicker 4.17.45 月曆 套件 安裝與試用https://shaurong.blogspot.com/2018/03/bootstrap-v3-datepicker-41745.html

[研究][ASP.NET][JavaScript] Bootstrap Datepicker 1.7.1 月曆 套件 安裝與試用https://shaurong.blogspot.com/2018/03/bootstrap-datepicker-171.html

[研究][ASP.NET][JavaScript] jQuery UI v1.12.1 的 Datepicker 月曆 套件 安裝與試用https://shaurong.blogspot.com/2017/07/jquery-ui-datepicker.html

2022年3月18日 星期五

[研究]ASP.NET + JavaScript Alert 彈出視窗換行測試 vs 彈出視窗沒出現研究

[研究]ASP.NET + JavaScript Alert 彈出對話盒視窗換行測試 vs 彈出對話盒視窗沒出現研究

2022-03-18

2022-03-19更新

嚴格來說,
\r (CR, Carriage Return)是回車,游標回到開頭,ASCII 碼 13 = \x0d,UniCode 碼 U+000D
\n (LF, Line Feed)是換行,游標到下一行,沒有回到開頭,ASCII 碼 10 = \x0a,UniCode 碼 U+000A

但在不同的場合,可能只使用其中一種就兼具回到開頭和換行。https://zh.wikipedia.org/wiki/%E6%8F%9B%E8%A1%8C

  • LF:在Unix或Unix相容系統(GNU/Linux,AIX,Xenix,Mac OS X,...)、BeOS、Amiga、RISC OS
  • CR+LF:DOS(MS-DOS、PC-DOS等)、微軟視窗作業系統(Microsoft Windows)、大部分非Unix的系統
  • CR:Apple II家族,Mac OS至版本9

Test.htm

<html>
<head>
<script language='javascript' defer>alert('換行測試1\n換行測試');</script>
<script language='javascript' defer>alert('換行測試2\r換行測試');</script>
<script language='javascript' defer>alert('換行測試3\\n換行測試');</script>
<script language='javascript' defer>alert('換行測試4\\r換行測試');</script>
<script language='javascript' defer>alert('換行測試5\n\r換行測試');</script>
<script language='javascript' defer>alert('換行測試6\r\n換行測試');</script>
</head>
</html>

結果如下 ( 有些測試使用雙倒斜線,這是為了測試脫序字元,做個比較)






單獨的 \r 和 \n  意義相同,但 \n\r 和 \r\n 意義不同。

兩個 \\ 會當成真正要顯示 \ 使用,而非有特殊用途。

********************************************************************************

Visual Studio 2022 + ASP.NET + WebForm + Web Application 

WebForm1.aspx

using System;
using System.Web.UI;

namespace WebApplication16
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試1<br />換行測試');</script>");
        }
        protected void Button2_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試2\\n換行測試');</script>");
        }
        protected void Button3_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試3\\r換行測試');</script>");
        }
        protected void Button4_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試4\n換行測試');</script>");
        }
        protected void Button5_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試5\r換行測試');</script>");
        }
        protected void Button6_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試6\u000d換行測試');</script>");
        }
        protected void Button7_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試7\u000a換行測試');</script>");
        }
        protected void Button8_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試8\\u000d換行測試');</script>");
        }
        protected void Button9_Click(object sender, EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('換行測試9\\u000a換行測試');</script>");
        }
    }
}

結果如下 ( 有些測試使用雙倒斜線,這是為了測試脫序字元,做個比較)






可以發現 ASP.NET 用 Page.ClientScript.RegisterStartupScript 來使用 JavaScript Alert 視窗時,必須使用兩個倒斜線才可以讓對話盒視窗顯示和換行,否則連彈出視窗都沒了。

********************************************************************************

2022-03-19

Test2.htm

<html>
<head>
<script language='javascript' defer>alert('換行測試11
換行測試');</script>
</head>
</html>

結果不會有彈出視窗,表示alert的訊息不可以自己手動先換行。

********************************************************************************
結論
*alert的訊息不可以自己手動先換行,不會有彈出視窗。<br \> 只會被當成文字顯示。
*alert中單獨的 \r 和 \n  意義相同,但 \n\r 和 \r\n 意義不同。兩個 \\ 會當成真正要顯示 \ 使用,結果不會有彈出視窗。
*ASP.NET的Page.ClientScript.RegisterStartupScript,必須使用兩個倒斜線才可以讓對話盒視窗顯示和換行,否則連彈出視窗都沒了。

(完)

相關

[研究][ASP.NET]JavaScript alert對話盒視窗彈出位置測試
https://shaurong.blogspot.com/2022/04/aspnetjavascript-alert.html

[研究]ASP.NET + JavaScript Alert 彈出視窗換行測試 vs 彈出視窗沒出現研究
https://shaurong.blogspot.com/2022/03/javascript-alert.html

[研究]HTML, CSS, JavaScript, jQuery, jQuery UI, Bootstrap 彈出對話盒視窗
https://shaurong.blogspot.com/2020/11/html-css-javascript-jquery-jquery-ui.html

[研究]]JavaScript] 用 orangehill / bootstrap-session-timeout 做 Session Time Out 前 N 秒自動彈出對話盒視窗
https://shaurong.blogspot.com/2020/11/javascript-orangehill-bootstrap-session.html

[研究][JavaScript] 用 session-timeout.js 做 Session Time Out 前 N 秒自動彈出對話盒視窗
https://shaurong.blogspot.com/2020/11/javascript-session-timeoutjs-session.html

[研究][JavaScript]Master Page 用 idle-timer.js 做 Session Time Out 前 N 秒自動彈出倒數計時對話盒視窗
https://shaurong.blogspot.com/2020/11/javascriptcaspnetwebform-master-page.html

[研究][JavaScript] 用 idle-timer.js 做 Session Time Out 前 N 秒自動彈出倒數計時對話盒視窗
https://shaurong.blogspot.com/2020/11/javascript-idle-timerjs-session-time.html

[研究][JavaScript] 用 timeout-dialog.js 做 Session Time Out 前 60 秒自動彈出倒數計時對話盒視窗
https://shaurong.blogspot.com/2020/11/javascript-timeout-dialogjs-session.html

[研究][C#] [ASP.NET] [JavaScript] 彈出視窗 (對話盒)
https://shaurong.blogspot.com/2020/04/c-aspnet-javascript.html

[研究][C#] [ASP.NET] [JavaScript] 彈出視窗
https://shaurong.blogspot.com/2017/06/c-aspnet-javascript.html


[研究][C#][ASP.NET]計算字串SHA256值

[研究][C#][ASP.NET]計算字串SHA256值

2022-3-17

參考

HashAlgorithm.ComputeHash 方法 (System.Security.Cryptography) | Microsoft Docs

https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.hashalgorithm.computehash?view=net-6.0


private string GetStringSHA256(string input)
{
    using (SHA256 sha256Hash = SHA256.Create())
    {
        byte[] data = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
        return sBuilder.ToString();
    }
}


可以下載 HashCalc 軟體測試比較

http://www.slavasoft.com/hashcalc/index.htm

注意,對字串和對檔案做SHA256是兩碼子事情。

(完)

2022年3月17日 星期四

[研究]Git commit失敗之解決 - git did not exit cleanly (exit code 1)

[研究]Git commit 出現 git did not exit cleanly (exit code 1) 問題之解決

2022-03-17


git.exe push --progress "origin" master:master
To http://網址IP:3000/路徑/專案.git
! [rejected]          master -> master (fetch first)
error: failed to push some refs to 'http://網址IP:3000/路徑/專案.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.


git did not exit cleanly (exit code 1) (1375 ms @ 日期時間)

Dealing with non-fast-forward errors - GitHub Docs

https://docs.github.com/en/get-started/using-git/dealing-with-non-fast-forward-errors

********************************************************************************

原因:

一般這是多人開發,大家同樣簽出 (checkout) 同一版本,有人比你早簽入 (checkin),你再簽入時發生。

解決:

假設敝人Git專案放自己 D:\Git\Project1 目錄,敝人不擅 Git 命令,所以是用GUI工具。

TortoiseGit – Windows Shell Interface to Git
https://tortoisegit.org/

WinMerge - You will see the difference…
https://winmerge.org/

測試1. Git Clone 把 Git Server 上的clone 到自己電腦 D:\Git\Project2 目錄,用 WinMerge 軟體比對,把 Project2 中較新的檔案拷貝到 Project1後,再把Project1目錄 Git Commit,結果,失敗。

測試2. 把 D:\Git\Project1 改名 D:\Git\Project1.New,Git Clone 把 Git Server 上的clone 到自己電腦 D:\Git\Project1 目錄,用 WinMerge 軟體比對,把 D:\Git\Project1.New中較新的檔案拷貝到 Project1後,再 Git Commit,結果,成功。

(完)

2022年3月9日 星期三

[研究][ASP.NET]索引和長度必須參考字串中的位置。參數名稱: length

[研究][ASP.NET]索引和長度必須參考字串中的位置。參數名稱: length

2022-03-09

相同 CODE,開發機正常,測試機異常;最後把 try catch 拿掉或註解掉 (如下)

try
{

}
catch (Exception)
{
    throw;
}

再把 目的網站的 Web.Config 中客製化錯誤暫時從

<customErrors defaultRedirect="~/GeneralError.aspx" mode="RemoteOnly"></customErrors>

改為

<customErrors customErrors mode="Off"></customErrors>

強迫讓出錯的CODE顯示出來,錯誤終於出現了


雖然紅字標註在 1250行,其實這4行算是同一行 (以分號來看)


MailKit.Net.Smtp.SmtpClient client = new MailKit.Net.Smtp.SmtpClient
{
    ServerCertificateValidationCallback = (s, c, h, ee) => true
};

把 ServerCertificateValidationCallback 那行註解掉,變成這行出錯

if (localIP.Substring(0, 11) == "192.168.123.100")

因為測試機的IP沒有長到11個字元,結果就出錯了。

註解:至於 Visual Studio 為何報錯行,就不清楚了。

(完)

相關

[研究]Fortify SCA報告Insecure SSL: Server Identity Verification Disabled
http://shaurong.blogspot.com/2021/11/fortify-scainsecure-ssl-server-identity.html


[研究][ASP.NET]GridView 沒資料時時也顯示表頭欄位名稱

[研究][ASP.NET]GridView 沒資料時時也顯示表頭欄位名稱

2022-03-09

GridView如果SELECT沒有撈到任何資料,預設是空白一片,不顯示任何東西。

要自己手動設定 EmptyDataText 值,就會顯示該值,例如:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
    Inherits="WebApplication12.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>" 
                SelectCommand="SELECT * FROM [Products]">
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
                DataKeyNames="no" DataSourceID="SqlDataSource1" EmptyDataText="無資料">
                <Columns>
                    <asp:BoundField DataField="no" HeaderText="no" InsertVisible="False" 
                        ReadOnly="True" SortExpression="no" />
                    <asp:BoundField DataField="product" HeaderText="product" SortExpression="product" />
                    <asp:BoundField DataField="price" HeaderText="price" SortExpression="price" />
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>


如果希望,沒資料時時也顯示表頭欄位名稱,GridView 並不支援,沒有簡便設定方式,只能自己寫 CODE 或用其他方式達成,例如用 <EmptyDataTemplate> 達到。

在Visual Studio 的 GridView 上選「編輯樣板」


(下圖) 切換到 EmptyDataTemplate,隨便寫點字,選「結束樣板編輯」

回到 Visual Studio 2022 的「原始碼」畫面,手動編寫 <EmptyDataTemplate> 內容


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
    Inherits="WebApplication12.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>" 
                SelectCommand="SELECT * FROM [Products]">
            </asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
                DataKeyNames="no" DataSourceID="SqlDataSource1" EmptyDataText="自訂">
                <Columns>
                    <asp:BoundField DataField="no" HeaderText="no" InsertVisible="False" 
                        ReadOnly="True" SortExpression="no" />
                    <asp:BoundField DataField="product" HeaderText="product" SortExpression="product" />
                    <asp:BoundField DataField="price" HeaderText="price" SortExpression="price" />
                </Columns>
                <EmptyDataTemplate>
                    <table border="1">
                        <tr>
                            <td>no</td>
                            <td>product</td>
                            <td>price</td>
                        </tr>
                        <tr>
                            <td colspan="3">無資料</td>
                        </tr>
                    </table>
                </EmptyDataTemplate>
            </asp:GridView>
        </div>
    </form>
</body>
</html>

結果 EmptyDataText 有設定值 (不管是甚麼) 且<EmptyDataTemplate> 有內容,就會顯示 <EmptyDataTemplate> 內容。

因為這是硬生生手動作出的,不是 GridView 支援的,所以欄位有改名、增加、減少,這裡都不會自動反映。

(完)

[研究]SQL Server Management Studio (SMSS) 18 資料表設計時顯示描述欄位

[研究]SQL Server Management Studio (SMSS) 18 資料表設計時顯示描述欄位

2022-03-09

環境:SQL Server 2019 + SQL Server Management Studio (SMSS) 18.10

預設的 SQL Server Management Studio (SMSS) 設計模式,卻只有「資料行名稱」、「資料類型」、「允許NULL 」3個欄位,如果要增加顯示「描述」欄位呢?


重要,記得修改時,SQL Server Management Studio 必須是關閉的。

執行 regedit.exe,啟動「登錄編輯器」,搜尋 DataProject,找到

電腦\HKEY_CURRENT_USER\Software\Microsoft\SQL Server Management Studio\18.0_IsoShell\DataProject

SSVPropViewColumnsSQL70 從 1,2,6; 改為 1,2,6,17;

SSVPropViewColumnsSQL80 從 1,2,6; 改為 1,2,6,17;

(不同 SQL Server 版本,機碼路徑和機碼中的「名稱」可能不同)





啟動 SMSS 就可以看到多了「描述」欄位,

各數值意義如下:

1    Column Name

2    Data Type

3    Length

4    Precision

5    Scale

6    Allow Nulls

7    Default Value

8    Identity

9    Identity Seed

10    Identity Increment

11    Row GUID

12    Nullable

13    Condensed Type

14    Not for Replication

15    Formula

16    Collation

17    Description

(完)

相關

[研究]SQL Server Management Studio (SMSS) 18 資料表設計時顯示描述欄位
http://shaurong.blogspot.com/2022/03/sql-server-management-studio-smss-18.html