[研究]ASP.NET WebForm建立使用Microsoft AspNet Identity身分識別機制的範例程式
2026-01-19
需要一個使用Microsoft AspNet Identity身分識別機制的範例程式做測試,不想自己寫,下面可以快速建立一個。
(完)
[研究]ASP.NET WebForm建立使用Microsoft AspNet Identity身分識別機制的範例程式
2026-01-19
需要一個使用Microsoft AspNet Identity身分識別機制的範例程式做測試,不想自己寫,下面可以快速建立一個。
(完)
[研究]ASP.NET + WebForm + SQL Server 開發,安裝勾選建議?
2025-12-04
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 20.2
ASP.NET + WebForm + SQL Server 開發,安裝勾選建議?
① 網頁伺服器 → 一般 HTTP 功能
| 功能 | 是否需要 | 說明 |
|---|---|---|
| HTTP 錯誤 | ✔ 必要 | ASP.NET 會使用自訂錯誤頁 |
| 預設文件 | ✔ 必要 | 預設讀取 default.aspx |
| 靜態內容 | ✔ 必要 | 載入 JS / CSS / 圖檔 |
| 瀏覽目錄 | ❌ 不建議 | 通常不應讓使用者看到目錄 |
| HTTP 重新導向 | ✔ 常用 | 301/302 轉址 |
| WebDAV 發佈 | ❌ 禁用 | 高風險,不需要 WebDAV |
② 安全性(需依網站需求,但常用如下)
| 功能 | 是否需要 | 說明 |
|---|---|---|
| 要求篩選 (Request Filtering) | ✔ 必要 | 防止惡意請求(預設即建議啟用) |
| 基本驗證 | ❌ 除非需求 | 網站使用 Forms Auth 時不需要 |
| Windows 驗證 | ❌ 依需求 | 若為內部 AD 驗證才勾 |
| IP 及網域限制 | ✔ 建議 | 若有管理後台,可限制來源 IP |
| URL 授權 | ✔ 若使用 | 可限制 URL ACL,但 WebForms 通常使用 Web.config 授權 |
不勾選(安全性高風險):IIS 用戶端憑證、集中式 SSL、摘要式驗證、用戶端憑證對應驗證
③ 狀況及診斷(視 Debug 需求)
| 功能 | 是否需要 | 說明 |
|---|---|---|
| HTTP 記錄 | ✔ 必要 | 基本 IIS log |
| 要求監視器 | ✔ 建議 | 分析長延遲請求 |
| 追蹤(Tracing) | ❌ 生產環境不要 | 會暴露太多資訊 |
| 自訂記錄 / ODBC 記錄 | ❌ 不建議 | 通常無用且拖慢性能 |
④ 效能
| 功能 | 是否需要 | 說明 |
|---|---|---|
| 靜態內容壓縮 | ✔ 建議 | 減少流量,前端效能好 |
| 動態內容壓縮 | ✔ 建議 | 支援 ASPX 壓縮,節省頻寬 |
⑤ 應用程式開發(WebForms 必要)
| 功能 | 是否需要 | 說明 |
|---|---|---|
| .NET 擴充性 4.7 | ✔ 必要 | WebForms .NET Framework 執行必備 |
| ASP.NET 4.7 | ✔ 必要 | WebForms 正式執行環境 |
| ISAPI 擴充程式 | ✔ 必要 | ASP.NET 需使用 |
| ISAPI 篩選器 | ✔ 必要 | ASP.NET Pipeline |
| CGI | ❌ 不需要 | 若無 Perl/PHP 不要開 |
| WebSocket 通訊協定 | ❌ 依需求 | WebForms 大多不需要 |
| 伺服器端包含 | ❌ 不需要 | 不使用 SSI 時不用開 |
| 應用程式初始化 | ✔ 建議 | 可讓 AppPool 啟動時 Preload |
注意:若你專案不是 .NET 3.5,就不要開啟 .NET 3.5 / ASP.NET 3.5 以降低攻擊面。
⑥ 管理工具(管理必備)
| 功能 | 是否需要 | 說明 |
|---|---|---|
| IIS 管理主控台 | ✔ 必要 | 顯示 IIS GUI |
| IIS 管理指令碼及工具 | ✔ 建議 | 方便使用 appcmd |
| 管理服務 | ❌ 依需求 | 若需遠端 IIS 管理才勾 |
| IIS6 管理相容性 (全套) | ❌ 除非舊程式需要 | 新架構不需 IIS6 metabase |
❌ 明確不建議勾選(提高風險且無必要)
| 項目 | 原因 |
|---|---|
| 瀏覽目錄 | 容易洩漏檔案 |
| WebDAV 發行 | 高風險,容易被攻擊 |
| 基本驗證 / 摘要式驗證 | 非必要,安全性較低 |
| 用戶端憑證對應驗證 | 不需要 |
| 追蹤(Tracing) | 生產環境不安全 |
| CGI | 不需要 |
| FTP服務 / FTP擴充性 | 不建議在同台 IIS 使用 FTP |
| IIS6 相關 | 不用 Metabase 就不需 |
📌 最常用標準 WebForms 伺服器配置(推薦直接照這表啟用)
✔ 你應該勾的(推薦列表)
❌ 不要勾的(能關就關)
相關
[研究]ASP.NET WebForm + SQL Server 2019 網站的AP Log資料表推薦?
2025-11-22
突然想到,問問看 ChatGPT 的 APLog 建議。
開發一個 ASP.NET WebForm + SQL Server 2019 網站,請推薦 DB 中 Log table 有哪欄位,欄位型態(含長度、是否預設值、預設值、是否允許 NULL、、、) 分別是是甚麼 ? 表格呈現 ?
ChatGPT
✅ 一、Log Table 欄位建議(最推薦版本)
| 欄位名稱 | 型態 | 長度 | NULL? | 預設值 | 說明 |
|---|---|---|---|---|---|
| LogID | BIGINT |
— | NOT NULL | IDENTITY(1,1) | Primary Key,自動遞增 |
| LogTime | datetime2(3) |
— | NOT NULL | SYSDATETIME() |
建議記到毫秒(.000~.999) |
| Level | varchar(20) |
20 | NOT NULL | 'INFO' |
Log 等級,例如 INFO / WARN / ERROR |
| UserID | varchar(50) |
50 | NULL | NULL | 來源使用者代號(可 NULL) |
| ClientIP | varchar(45) |
45 | NULL | NULL | IPv4/IPv6 都可記錄 |
| PageName | varchar(200) |
200 | NULL | NULL | 記錄 ASPX 頁面(或 API 名稱) |
| Action | varchar(200) |
200 | NULL | NULL | 使用者動作、事件名 |
| Message | nvarchar(max) |
— | NULL | NULL | 主訊息、簡述 |
| Detail | nvarchar(max) |
— | NULL | NULL | 完整訊息(如 Exception.ToString) |
| MachineName | varchar(100) |
100 | NOT NULL | HOST_NAME() |
伺服器名稱 |
| AppName | varchar(50) |
50 | NOT NULL | 'WebFormSite' |
系統識別名(可改) |
| TraceID | varchar(50) |
50 | NULL | NULL | 用於跨 API、跨系統追蹤 |
✔ 為何選用 datetime2(3)?
datetime2(3)
✔ 為何 Level、PageName、Action 建議 varchar?
因為:
✔ 有沒有必要建立索引?
建議以下 Index:
✅ 二、SQL 建議 DDL
CREATE TABLE dbo.Logs
(
LogID BIGINT IDENTITY(1,1) NOT NULL PRIMARY KEY,
LogTime datetime2(3) NOT NULL DEFAULT SYSDATETIME(),
Level varchar(20) NOT NULL DEFAULT ('INFO'),
UserID varchar(50) NULL,
ClientIP varchar(45) NULL,
PageName varchar(200) NULL,
Action varchar(200) NULL,
Message nvarchar(max) NULL,
Detail nvarchar(max) NULL,
MachineName varchar(100) NOT NULL DEFAULT HOST_NAME(),
AppName varchar(50) NOT NULL DEFAULT ('WebFormSite'),
TraceID varchar(50) NULL
);
|
▶ 三、在 ASP.NET WebForm GridView 的呈現建議
GridView 最常顯示欄位:
| 顯示 | 不顯示(或隱藏) |
|---|---|
| LogTime | LogID |
| Level | MachineName |
| UserID | AppName |
| ClientIP | TraceID |
| PageName | Detail(按按鈕展開) |
| Action | |
| Message |
✔ GridView 最佳呈現(程式碼示例)
.aspx
<asp:GridView ID="gvLog" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="LogTime" HeaderText="時間"
DataFormatString="{0:yyyy-MM-dd HH:mm:ss.fff}" />
<asp:BoundField DataField="Level" HeaderText="層級" />
<asp:BoundField DataField="UserID" HeaderText="使用者" />
<asp:BoundField DataField="ClientIP" HeaderText="IP" />
<asp:BoundField DataField="PageName" HeaderText="頁面" />
<asp:BoundField DataField="Action" HeaderText="動作" />
<asp:BoundField DataField="Message" HeaderText="訊息" />
<!-- Detail 隱藏,改成按鈕彈出 -->
<asp:TemplateField HeaderText="詳細">
<ItemTemplate>
<asp:Button runat="server" Text="查看"
CommandName="ViewDetail"
CommandArgument='<%# Eval("LogID") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
|
📌 四、如果需要寫入程式碼(C# 範例)
Default.aspx
public static void WriteLog(string level, string user, string page, string action, string msg, string detail)
{
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO Logs (Level, UserID, PageName, Action, Message, Detail, ClientIP)
VALUES (@Level, @UserID, @PageName, @Action, @Message, @Detail, @IP)
", conn))
{
cmd.Parameters.AddWithValue("@Level", level);
cmd.Parameters.AddWithValue("@UserID", (object)user ?? DBNull.Value);
cmd.Parameters.AddWithValue("@PageName", page);
cmd.Parameters.AddWithValue("@Action", action);
cmd.Parameters.AddWithValue("@Message", msg);
cmd.Parameters.AddWithValue("@Detail", (object)detail ?? DBNull.Value);
cmd.Parameters.AddWithValue("@IP", HttpContext.Current.Request.UserHostAddress);
conn.Open();
cmd.ExecuteNonQuery();
}
}
|
********************************************************************************
這是 ASP.NET WebForm 繁體中文網站,為何是否允許NULL 建議用 NULL ? 某些 "預設值" 建議用 NULL,而不是 N'' 空字串 ? 型態建議用 varchar,而不是 nvarchar ?
ChatGPT
✅ 為何 大部分欄位建議允許 NULL?
✔ 1. Log 本質是「紀錄事件」,不是所有欄位每次都會有資料
👉 因此 強迫 NOT NULL + 空字串 會讓資料:難以判斷「真的沒有」 vs. 「空字串」
✔ 2. 空字串與 NULL 的語意完全不同
狀態 意義
NULL 這項資料「不存在」
''(空字串) 這項資料存在,只是內容是空
📌 Log 中最重要的是正確語意,因此推薦:
| 狀態 | 意義 |
|---|---|
| NULL | 這項資料「不存在」 |
| ''(空字串) | 這項資料存在,只是內容是空 |
❌ 若全部欄位 NOT NULL + 空字串,會變成問題
例如你要查「沒有 UserID 的 Log」:
你必須用:
WHERE UserID IS NULL OR UserID = ''
這會變得很亂,也容易寫錯。
🟦 結論
在 Log Table 中,多數欄位允許 NULL 才是真正國際慣例,也符合語意正確性。
✅ 為何某些欄位「預設值」建議用 NULL,而不是 N'' 空字串?
✔ 1. 預設值 NULL 表示「沒有提供」
例如呼叫 Log 方法時沒有傳 Action,你希望 DB 記錄「無動作」,不是「空白動作」。
✔ 2. 空字串會破壞查詢語意
空字串實際上是一個「值」,但它不代表不存在。
✔ 3. 節省儲存空間
NULL 在 SQL Server 的儲存是 比空字串更省空間的,因為儲存格式不同。
✔ 4. 避免 Query Index 汙染
使用空字串會造成 B-Tree index 多一個不必要的 entry。
✔ 為何欄位型態建議用 varchar 而不是 nvarchar?
即使你的網站是 繁體中文網站,仍然有三個核心原因:
🎯 核心原因 1:Log 中大部分欄位是英文,不需 Unicode。
🎯 核心原因 2:varchar 效能與空間比 nvarchar 更好
在 SQL Server 中:
varchar 為 1 byte / 字元
nvarchar 為 2 bytes / 字元
Log 可能幾百萬筆,差異大:
| 型態 | 儲存空間 | 意義 |
|---|---|---|
| varchar(50) | 50 bytes | 較小、較快 |
| nvarchar(50) | 100 bytes | 大 2 倍,index 也大 2 倍 |
Log table 通常很大,使用 varchar 可節省大量空間並提升查詢速度。
🎯 核心原因 3:繁體中文只會出現在 Message / Detail
這兩個欄位我已建議用:
nvarchar(max)
nvarchar(max)
這些欄位確實會包含中文、例外訊息、堆疊資訊。
但其他用來辨識頁面、欄位、行為的欄位多為英文,varchar 完全足夠。
********************************************************************************
查詢條件,TextBox1 為完全比對,空白時查全部;TextBox2 為完全比對,空白時查全部,否則使用 LIKE,code 盡量不寫 aspx.cs 中,寫在 .aspx 中就好
.aspx
<asp:TextBox ID="TextBox1" runat="server" />
<asp:TextBox ID="TextBox2" runat="server" />
<asp:Button ID="btnSearch" runat="server" Text="查詢" />
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:MyConn %>"
SelectCommand="
SELECT *
FROM LogTable
WHERE
-- TextBox1:空白查全部,有值則完全比對
(@p1 = '' OR Column1 = @p1)
AND
-- TextBox2:空白查全部,有值則 LIKE 模糊比對
(@p2 = '' OR ISNULL(Column2, '') LIKE @like_p2)
">
<SelectParameters>
<asp:ControlParameter Name="p1" ControlID="TextBox1" PropertyName="Text" />
<asp:ControlParameter Name="p2" ControlID="TextBox2" PropertyName="Text" />
<!-- 給 TextBox2 做 LIKE 用 -->
<asp:ControlParameter Name="like_p2"
ControlID="TextBox2"
PropertyName="Text"
ConvertEmptyStringToNull="false"
DefaultValue="" />
</SelectParameters>
<!-- 調整參數:在 Selecting 事件中加入 '%'(無需寫 aspx.cs!) -->
<SelectParameters>
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
|
.aspx
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
OnSelecting="SqlDataSource1_Selecting"
...
>
|
.aspx
<script runat="server">
protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
{
string p2 = (string)e.Command.Parameters["@p2"].Value;
// TextBox2 空白:查全部 → LIKE 條件會被 (@p2 = '') 篩掉
if (string.IsNullOrEmpty(p2))
{
e.Command.Parameters["@like_p2"].Value = "";
}
else
{
// LIKE '%keyword%'
e.Command.Parameters["@like_p2"].Value = "%" + p2 + "%";
}
}
</script>
|
(完)
[研究]ASP.NET WebForm 讓 Fortify SAST (SCA) 掃描結果 Critlcal, High, Medium, Low, Info 都各自剛好有一項的程式
2025-09-05
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 20.2
********************************************************************************
ASP.NET WebForm, 請給我完整 Default.aspx 和 Default.aspx.cs 內容,可以讓 Fortify SAST (SCA) 掃描有 Critlcal, High, Medium, Low, Info 都各自剛好有一項結果的程式
ChatGPT 說:
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>
<h2>Fortify SAST Vulnerability Test</h2>
<asp:Label ID="lblInput" runat="server" Text="Enter text: "></asp:Label>
<asp:TextBox ID="txtInput" runat="server"></asp:TextBox>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" />
<br />
<br />
<asp:Label ID="lblOutput" runat="server" Text=""></asp:Label>
</div>
</form>
</body>
</html>
|
Default.aspx.cs
using System;
using System.Data.SqlClient;
using System.IO;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
// Hardcoded password (Low severity / Info)
private string hardcodedPassword = "P@ssw0rd123";
protected void Page_Load(object sender, EventArgs e)
{
// Information Disclosure (Low/Info)
Response.Headers.Add("X-Powered-By", "ASP.NET WebForms Fortify Test");
if (!IsPostBack)
{
// Logging sensitive info (Medium)
File.AppendAllText(Server.MapPath("~/log.txt"), "Page loaded at " + DateTime.Now
+ " with password: " + hardcodedPassword + Environment.NewLine);
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
string userInput = txtInput.Text;
// 1. XSS (High)
lblOutput.Text = "You entered: " + userInput;
// 2. SQL Injection (Critical)
string connString = "Data Source=.;Initial Catalog=TestDB;Integrated Security=True";
string query = "SELECT * FROM Users WHERE Username = '" + userInput + "'";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
lblOutput.Text += "<br/>User: " + reader["Username"].ToString();
}
}
// 3. Insecure Random (Low/Info)
Random rand = new Random();
int weakRandom = rand.Next(1000);
lblOutput.Text += "<br/>Random number: " + weakRandom;
// 4. Potential Path Traversal (Medium)
string path = Server.MapPath("~/uploads/") + userInput + ".txt";
if (File.Exists(path))
{
lblOutput.Text += "<br/>File found: " + path;
}
}
}
}
|
********************************************************************************
實際測試
結果
似乎要 Critlcal, High, Medium, Low, Info 都各自剛好有一項的程式對 ChatGPT 是難以做到的,但至少數量不高,也各種都有,方便其他測試。
(完)
相關
[研究]ASP.NET WebForm 專案第三方元件後升級編譯出錯
2025-08-08
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
已開始重建...
1>------ 已開始全部重建: 專案: WebApplition1, 組態: Debug Any CPU ------
1> 請考慮將組件 "Autofac, Culture=neutral, PublicKeyToken=17863af14b0044da" 的 app.config 從版本 "8.3.0.0" [] 重新對應至版本 "8.4.0.0" [D:\Solution1\WebApplication1\packages\Autofac.8.4.0\lib\netstandard2.0\Autofac.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "ExtendedNumerics.BigDecimal, Culture=neutral, PublicKeyToken=65f1315a45ad8949" 的 app.config 從版本 "3000.0.4.132" [] 重新對應至版本 "3001.0.1.201" [D:\Solution1\WebApplication1\packages\ExtendedNumerics.BigDecimal.3001.0.1.201\lib\net48\ExtendedNumerics.BigDecimal.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "Microsoft.Bcl.AsyncInterfaces, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\Microsoft.Bcl.AsyncInterfaces.9.0.8\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "Microsoft.Owin, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 的 app.config 從版本 "4.2.2.0" [] 重新對應至版本 "4.2.3.0" [D:\Solution1\WebApplication1\packages\Microsoft.Owin.4.2.3\lib\net45\Microsoft.Owin.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "Microsoft.Owin.Security, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 的 app.config 從版本 "4.2.2.0" [] 重新對應至版本 "4.2.3.0" [D:\Solution1\WebApplication1\packages\Microsoft.Owin.Security.4.2.3\lib\net45\Microsoft.Owin.Security.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "Microsoft.Owin.Security.Cookies, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 的 app.config 從版本 "4.2.2.0" [] 重新對應至版本 "4.2.3.0" [D:\Solution1\WebApplication1\packages\Microsoft.Owin.Security.Cookies.4.2.3\lib\net45\Microsoft.Owin.Security.Cookies.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "Microsoft.Owin.Security.OAuth, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 的 app.config 從版本 "4.2.2.0" [] 重新對應至版本 "4.2.3.0" [D:\Solution1\WebApplication1\packages\Microsoft.Owin.Security.OAuth.4.2.3\lib\net45\Microsoft.Owin.Security.OAuth.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Collections.Immutable, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Collections.Immutable.9.0.8\lib\net462\System.Collections.Immutable.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Diagnostics.DiagnosticSource, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Diagnostics.DiagnosticSource.9.0.8\lib\net462\System.Diagnostics.DiagnosticSource.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Formats.Asn1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Formats.Asn1.9.0.8\lib\net462\System.Formats.Asn1.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Security.Permissions, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Security.Permissions.9.0.8\lib\net462\System.Security.Permissions.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Text.Encoding.CodePages, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Text.Encoding.CodePages.9.0.8\lib\net462\System.Text.Encoding.CodePages.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Text.Encodings.Web, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Text.Encodings.Web.9.0.8\lib\net462\System.Text.Encodings.Web.dll],以解決衝突並避免出現警告。
1> 請考慮將組件 "System.Text.Json, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" 的 app.config 從版本 "9.0.0.6" [] 重新對應至版本 "9.0.0.8" [D:\Solution1\WebApplication1\packages\System.Text.Json.9.0.8\lib\net462\System.Text.Json.dll],以解決衝突並避免出現警告。
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2203,5): warning MSB3247: 在同一個相依組件的不同版本之間發現衝突。請在 Visual Studio 中按兩下這個警告 (或選取後按 Enter) 解決這些衝突,或者將下列繫結重新導向加到應用程式組態檔中的 [執行階段] 節點:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Autofac" culture="neutral" publicKeyToken="17863af14b0044da" /> <bindingRedirect oldVersion="0.0.0.0-8.4.0.0" newVersion="8.4.0.0" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="ExtendedNumerics.BigDecimal" culture="neutral" publicKeyToken="65f1315a45ad8949" /> <bindingRedirect oldVersion="0.0.0.0-3001.0.1.201" newVersion="3001.0.1.201" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin" culture="neutral" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-4.2.3.0" newVersion="4.2.3.0" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" culture="neutral" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-4.2.3.0" newVersion="4.2.3.0" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.Cookies" culture="neutral" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-4.2.3.0" newVersion="4.2.3.0" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.OAuth" culture="neutral" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-4.2.3.0" newVersion="4.2.3.0" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Collections.Immutable" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Diagnostics.DiagnosticSource" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Formats.Asn1" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Security.Permissions" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Text.Encoding.CodePages" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Text.Encodings.Web" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Text.Json" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /> <bindingRedirect oldVersion="0.0.0.0-9.0.0.8" newVersion="9.0.0.8" /> </dependentAssembly> </assemblyBinding> |
********************************************************************************
解決
最後把這份砍了,把先前備份的 Source Code 複製一份過來,把 D:\Solution1\WebApplication1\packages 目錄整個砍了,再做一次 NuGet 升級,正常了。
(完)
相關
[研究]ASP.NET WebForm 執行過久跳轉 Exception 畫面之處理
2025-07-10、2025-12-15
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 20
********************************************************************************
ASP.NET WebForm 同一個 .aspx 網頁,因為計算的東西複雜,在效能好的機器上正常運作,在效能較差虛擬機上,執行一陣子自動跳轉到 Exception 畫面。
ChatGPT 回答的太拉雜囉嗦,整理數次詢問的結果。
全域設定,可改 Web.Config,預設 90秒, 最大值(上限):Int32.MaxValue 秒,2,147,483,647 秒 ≒ 68 年
<configuration>
<system.web>
<httpRuntime executionTimeout="300" />
</system.web>
</configuration>
|
只改單一網頁,注意,Server.ScriptTimeout 設定超過 executionTimeout 是無用的。
protected void Button1_Click(object sender, EventArgs e)
{
Server.ScriptTimeout = 300;
try
{
// 假設是複雜計算
DoHeavyCalculation();
lblResult.Text = "計算完成。";
}
catch (TimeoutException ex)
{
lblResult.Text = "計算逾時,請簡化條件或稍後再試。";
// 可以記錄詳細例外訊息
LogException(ex);
}
catch (Exception ex)
{
lblResult.Text = "發生錯誤:" + ex.Message;
LogException(ex);
}
}
|
另外考慮是否因為去 DB 中抓資料時間超過,CommandTimeout 預設 30 秒,下面可以改為 180 秒。
SqlCommand command = new SqlCommand("your SQL here", connection);
command.CommandTimeout = 180; // 改為 3 分鐘
ㄌ |
捕捉例外
try
{
using (SqlConnection connection = new SqlConnection("your connection string"))
{
connection.Open();
SqlCommand command = new SqlCommand("your SQL here", connection);
command.CommandTimeout = 30;
using (SqlDataReader reader = command.ExecuteReader())
{
// 處理資料
}
}
}
catch (SqlException ex)
{
if (ex.Number == -2) // timeout
{
// 處理查詢逾時
Response.Write("資料庫查詢逾時,請稍後再試。");
}
else
{
// 處理其他 SQL 錯誤
Response.Write("資料庫錯誤:" + ex.Message);
}
}
catch (Exception ex)
{
// 處理非 SQL 的其他例外
Response.Write("系統發生錯誤:" + ex.Message);
}
|
另外也可能是記憶體不足,或 IIS Request Timeout 設定過短 (可在 IIS 裡 Application Pool → Limits → Request Timeout 設定 ),或 Proxy、CDN、、、等因素。
**********
使用 GrdView1 和 SqlDataSource1 發生 "等候操作已逾時。增加 DB 連線時間
protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
{
// System.ComponentModel.Win32Exception: 等候操作已逾時。
// System.Data.SqlClient.SqlException (0x80131904): 執行逾時到期。
e.Command.CommandTimeout = 60;
}
|
**********
敝人最後是靠改成下面解決問題。
<httpRuntime executionTimeout="300" />
command.CommandTimeout = 300; // 改為 5 分鐘
(完)
相關
[研究]ASP.NET WebForm 為何會有 WebResource.axd 和 ScriptResource.axd
2025-07-10
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 20
********************************************************************************
ASP.NET WebForm 為何會有 WebResource.axd 和 ScriptResource.axd 存在 ? 但又非真正存在的網頁 ?WebResource.axd 和 ScriptResource.axd 差別 ?
ChatGPT 說:
在 ASP.NET WebForm 中,WebResource.axd 和 ScriptResource.axd 是 系統自動產生的虛擬資源(Virtual Resource),它們並不是實體存在於磁碟上的檔案或網頁,而是由 ASP.NET 處理程序(Handler)在執行階段動態生成並回應請求。
一、為何會有 WebResource.axd 和 ScriptResource.axd?
這兩個 .axd 是為了讓 ASP.NET 能夠:
二、差別在哪裡?
| 特徵 | WebResource.axd | ScriptResource.axd |
| 功能 | 傳遞 任意內嵌資源(圖片、CSS、JS 等) | 專門傳遞 AJAX Script 和 本地化 JS |
| 來源 | 任何嵌入 DLL 的資源 | ASP.NET AJAX Library(如 MicrosoftAjax.js) |
| 常見用途 | ImageButton 圖片、Validator 的 JS、CSS 等 | UpdatePanel、ScriptManager 所需的 JS |
| 用法產生方式 | 透過 Page.ClientScript.GetWebResourceUrl(...) 產生 | ScriptManager 控制項自動產生 |
| 可攜參數 | d=(資源識別碼),t=(組件)等 | 除了 d= 還有 culture=(語系)等參數 |
三、它們為什麼能運作(雖然不是真實檔案)?
這些 URL 被 web.config 中註冊的 HTTP Handler 攔截並處理:
<system.web>
<httpHandlers>
<add path="WebResource.axd" verb="GET" type="System.Web.Handlers.WebResourceHandler, System.Web" validate="true" />
<add path="ScriptResource.axd" verb="GET" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions" validate="true" />
</httpHandlers>
</system.web>
|
這些 Handler 會解析 URL 中的參數,然後從相對應的 DLL 中擷取嵌入的資源並回應給用戶端。
在 ASP.NET 2.0 以後(含 WebForms 應用程式)WebResource.axd 和 ScriptResource.axd 的 handler 預設內建於 ASP.NET runtime,不一定需要顯示在你的 Web.config 裡面。
四、是否能移除?
通常不能移除,因為 ASP.NET WebForm 的許多控制項會用到它們。如果強制禁止(例如在 web.config 移除 Handler 或 IIS 層級攔截),可能會導致以下問題:
五、安全考量
雖然 .axd 本身是安全的,仍建議:
********************************************************************************
(完)
相關
[研究]ASP.NET, WebForm, MasterPage, 跨站請求偽造 XSRF/CSRF(Cross-Site Request Forgery)防護
2025-06-24
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
Site1.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs"
Inherits="WebApplication1.Site1" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<asp:HiddenField ID="AntiCsrfToken" runat="server" />
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</form>
</body>
</html>
|
Site1.master.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Site1 : System.Web.UI.MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out Guid requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? string.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? string.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
|
Default.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</asp:Content>
|
Default.aspx.cs
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("XSRF (CSRF) 測試範例!");
}
}
}
|
用 OWASP Zed Attack Proxy (ZAP) 2.16.1 (2025-03-26 釋出) 測試
(完)
相關
[研究]ASP.NET, WebForm, 跨站請求偽造 XSRF/CSRF(Cross-Site Request Forgery)防護
2025-06-24
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
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">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</form>
</body>
</html>
|
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("XSRF (CSRF) 測試範例!");
}
}
}
|
用 OWASP Zed Attack Proxy (ZAP) 2.16.1 (2025-03-26 釋出) 測試
********************************************************************************
修改後 Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private string AntiXsrfTokenKey = "__AntiXsrfToken";
private string AntiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// 取得或產生 Anti-XSRF Token
AntiXsrfTokenValue = (string)ViewState[AntiXsrfTokenKey];
if (string.IsNullOrEmpty(AntiXsrfTokenValue))
{
AntiXsrfTokenValue = Guid.NewGuid().ToString("N");
ViewState[AntiXsrfTokenKey] = AntiXsrfTokenValue;
}
// 綁定驗證事件
Page.PreLoad += Page_PreLoad;
}
protected void Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// 首次載入,將 Token 存入 ViewState
ViewState[AntiXsrfTokenKey] = AntiXsrfTokenValue;
}
else
{
// PostBack 時比對 Token
if ((string)ViewState[AntiXsrfTokenKey] != AntiXsrfTokenValue)
{
throw new InvalidOperationException("Anti-XSRF 檢查失敗。");
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("XSRF (CSRF) 測試範例!");
}
}
}
|
再次測試
********************************************************************************
ZAP 為何仍出現 XSRF 警告?
因為 ZAP 看到:
<form method="post" action="./" id="form1">
代表:
所以:
********************************************************************************
再再次修改
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"> <asp:HiddenField ID="AntiCsrfToken" runat="server" /> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /> </form> </body> </html> |
Default.aspx.cs
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private const string AntiCsrfKey = "AntiCsrfTokenKey";
protected void Page_Init(object sender, EventArgs e)
{
// ViewStateUserKey 強化 ViewState 防偽造
if (Context.User.Identity.IsAuthenticated)
{
ViewStateUserKey = Session.SessionID;
}
else
{
ViewStateUserKey = Guid.NewGuid().ToString();
}
// 產生 Anti-CSRF Token
if (Session[AntiCsrfKey] == null)
{
Session[AntiCsrfKey] = Guid.NewGuid().ToString("N");
}
AntiCsrfToken.Value = Session[AntiCsrfKey].ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
// 驗證 Anti-CSRF Token
if (AntiCsrfToken.Value != (string)Session[AntiCsrfKey])
{
throw new InvalidOperationException("Anti-CSRF Token 驗證失敗,請重新整理頁面。");
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("XSRF (CSRF) 測試範例!");
}
}
}
|
再再次測試,防住 XSRF / CSRF 了。
********************************************************************************
相關
[研究]用ProDotNetZip取代DotNetZip處理.ods
2025-06-06
********************************************************************************
DotNetZip 最後版本 1.16.0
https://www.nuget.org/packages/dotnetzip/
This package has at least one vulnerability with high severity. It may lead to specific problems in your project. Try updating the package version.
This package has been deprecated as it is legacy and is no longer maintained.
此軟體包至少存在一個高危險漏洞。這可能會導致您的項目出現特定問題。請嘗試更新軟體包版本。
此軟體包已被棄用,因為它是舊版本,並且不再維護。
****************************************
上面畫面點右邊 Project website 後
https://github.com/haf/DotNetZip.Semverd
Please use System.IO.Compression! A fork of the DotNetZip project without signing with a solution that compiles cleanly. This project aims to follow semver to avoid versioning conflicts. DotNetZip is a FAST, FREE class library and toolset for manipulating zip files. Use VB, C# or any .NET language to easily create, extract, or update zip files.
請使用 System.IO.Compression! DotNetZip 專案的 fork 版本,無需簽名,可乾淨編譯。本專案旨在遵循語義版本控制 (semver) 以避免版本衝突。 DotNetZip 是一個快速、免費的類別庫和工具集,用於處理 zip 檔案。您可以使用 VB、C# 或任何 .NET 語言輕鬆建立、提取或更新 zip 檔案。
********************************************************************************
ProDotNetZip - NET Standard part of DotNetZip / Ionic's Zip Library
https://www.nuget.org/packages/ProDotNetZip
ProDotNetZip 沿用了 DotNetZip/Ionic Zip 原始程式碼,但僅限於 .NET Standard 部分,而非整個。命名空間保持不變,為 Ionic.Zip。
********************************************************************************
(完)
相關
[研究]用ProDotNetZip取代DotNetZip處理.ods
https://shaurong.blogspot.com/2025/06/prodotnetzipdotnetzipods.html
[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html
[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html
[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html
[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html
How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2
[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html
[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html
[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html
[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html
[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html
[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html
NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter
sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite
[研究]DropDownList從資料庫抓出的值,不在下拉選項中的處理
2025-04-01
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
DropDownListClass.cs
using System;
using System.Web.UI.WebControls;
namespace WebApplicationProject1.Controls
{
public class DropDownListClass : DropDownList
{
protected override void PerformDataBinding(System.Collections.IEnumerable dataSource)
{
// 過濾掉 DropDownList 在 DataBinding 時可能會發生的 Exception 問題!
// 如果 Exception 發生,預設會選取第一個下拉選項!
try
{
base.PerformDataBinding(dataSource);
}
catch (ArgumentOutOfRangeException ex)
{
ArgumentOutOfRangeException o = ex;
}
}
}
}
|
(完)
相關
[研究]ASP.NET, WebForm, Chart 長條圖測試(一)隱藏格線、顯示軸線
2025-03-05
環境:Visual Studio 2019 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
把Chart拖入「設計」畫面,會註冊元件。
ASPX
<asp:Chart ID="Chart1" runat="server" Width="600px" Height="400px"
BorderlineWidth="1" BorderlineColor="Black" BorderlineDashStyle="Solid">
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisX Title="xxx" Interval="1" LineWidth="1" LineColor="Black">
<MajorGrid Enabled="False" /> <!-- 隱藏 X 軸格線 -->
</AxisX>
<AxisY Title="yyy" LineWidth="1" LineColor="Black">
<MajorGrid Enabled="False" /> <!-- 隱藏 Y 軸格線 -->
</AxisY>
</asp:ChartArea>
</ChartAreas>
<Series>
<asp:Series Name="TotalLevelCountSeries" ChartType="Column" ChartArea="ChartArea1"
IsValueShownAsLabel="true" LabelForeColor="Blue" Font="Arial, 14pt, style=Bold" />
</Series>
</asp:Chart>
|
C#
Chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false; // 隱藏 X 軸格線 Chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false; // 隱藏 Y 軸格線 Chart1.ChartAreas["ChartArea1"].AxisX.LineWidth = 1; // 恢復 X 軸線條 Chart1.ChartAreas["ChartArea1"].AxisY.LineWidth = 1; // 恢復 Y 軸線條 Chart1.ChartAreas["ChartArea1"].AxisX.LineColor = System.Drawing.Color.Black; // 設定 X 軸顏色 Chart1.ChartAreas["ChartArea1"].AxisY.LineColor = System.Drawing.Color.Black; // 設定 Y 軸顏色 |
相關
[研究]ASP.NET, WebForm, Chart 雷達圖測試(三)多邊形、不填色、不顯示Y軸線
2025-03-04
環境:Visual Studio 2019 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
把Chart拖入「設計」畫面,會註冊元件。
Default3.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default3.aspx.cs" Inherits="WebApplication1.Default3" %>
<!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">
<asp:Chart ID="Chart1" runat="server">
<Titles>
<asp:Title Text="雷達圖1" Font="Arial, 14pt, style=Bold" />
</Titles>
<Series>
<asp:Series Name="Series1" ChartType="Radar">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Chart ID="Chart2" runat="server"
Width="400px" Height="400px"
BorderlineWidth="1" BorderlineColor="Black" BorderlineDashStyle="Solid" Palette="None">
<%--雷達圖外框線、填色 BorderlineWidth="1" BorderlineColor="Black" BorderlineDashStyle="Solid" Palette="None" --%>
<Titles>
<asp:Title Text="雷達圖2" Font="Arial, 14pt, style=Bold" />
</Titles>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisY LineWidth="0">
<MajorTickMark LineWidth="0" /> <%--Y軸不要顯示主要刻度標記--%>
<%--AxisY 的 LineWidth 是圓心拉出的線,0表示不畫那條線 --%>
<%--AxisY 的 MajorGrid 是繞著圓心的主要線 (圓形線、多邊形線或其他) --%>
<%--AxisY 的 MinorGrid 是繞著圓心的主要線 (圓形線、多邊形線或其他) --%>
<MajorGrid Enabled="true" LineColor="Orange" />
</AxisY>
</asp:ChartArea>
</ChartAreas>
<%--Series 是資料區域--%>
<Series>
<%--AreaDrawingStyle=Polygon 是把資料用多邊形線連起來
BorderWidth="3" BorderColor="Blue" 表連起來的線是藍色、線粗 3 pixels
Color="Transparent" 表示多邊形內部不填色
IsValueShownAsLabel="true" 表示顯示資料數值
LabelForeColor="Red" 表示顯示資料數值用紅色
--%>
<asp:Series Name="Series1" ChartType="Radar"
CustomProperties="AreaDrawingStyle=Polygon, DrawSideBySide=False"
BorderWidth="3" BorderColor="Blue" Color="Transparent"
IsValueShownAsLabel="true" LabelForeColor="Red" >
</asp:Series>
</Series>
</asp:Chart>
</form>
</body>
</html>
|
Default3.aspx.cs
using System;
using System.Web.UI.DataVisualization.Charting;
namespace WebApplication1
{
public partial class Default3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GenerateRadarChart();
}
}
private void GenerateRadarChart()
{
Series series = Chart1.Series["Series1"];
series.Points.AddXY("A", 87);
series.Points.AddXY("B", 62);
series.Points.AddXY("C", 93);
series.Points.AddXY("D", 54);
series.Points.AddXY("E", 75);
series.Points.AddXY("A", 87); // 雷達圖需要閉合
Series series2 = Chart2.Series["Series1"];
series2.Points.AddXY("A", 87);
series2.Points.AddXY("B", 62);
series2.Points.AddXY("C", 93);
series2.Points.AddXY("D", 54);
series2.Points.AddXY("E", 75);
series2.Points.AddXY("A", 87); // 雷達圖需要閉合
}
}
}
|
下圖
********************************************************************************
增加一行 CODE,右上圖的字母旁黑短線 (主要刻度標記) 就可以消失
<AxisY LineWidth="0">
<MajorTickMark LineWidth="0" /> <%--Y軸不要顯示主要刻度標記--%> |
********************************************************************************
補充:加大資料數值 (ASPX)
<Series>
<asp:Series Name="Series1" IsValueShownAsLabel="True" />
</Series> |
<Series>
<asp:Series Name="Series1" IsValueShownAsLabel="True" Font="Arial, 14pt, style=Bold" />
</Series> |
Chart1.Series["Series1"].IsValueShownAsLabel = true;
Chart1.Series["Series1"].Font = new System.Drawing.Font("Arial", 14, System.Drawing.FontStyle.Bold);
|
補充:資料點 (ASPX)
<asp:Chart ID="Chart1" runat="server" Width="600px" Height="400px">
<Series>
<asp:Series Name="Series1"
IsValueShownAsLabel="True"
MarkerStyle="Circle"
MarkerSize="8"
MarkerColor="Blue" />
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1" />
</ChartAreas>
</asp:Chart>
|
Chart1.Series["Series1"].IsValueShownAsLabel = true; // 設定資料點標記為圓形 Chart1.Series["Series1"].MarkerStyle = System.Web.UI.DataVisualization.Charting.MarkerStyle.Circle; Chart1.Series["Series1"].MarkerSize = 8; // 調整圓形大小 Chart1.Series["Series1"].MarkerColor = System.Drawing.Color.Blue; // 設定圓形顏色 |
相關
[研究]ASP.NET, WebForm, Chart 雷達圖測試(二)
2025-03-04
環境:Visual Studio 2019 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
把Chart拖入「設計」畫面,會註冊元件。
Default2.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default2.aspx.cs"
Inherits="WebApplication1.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>
<form id="form1" runat="server">
<asp:Panel ID="ChartPanel" runat="server"></asp:Panel>
</form>
</body>
</html>
|
Default2.aspx.cs
using System;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadChart();
}
}
private void LoadChart()
{
for (int i = 0; i <= 63; i++)
{
Chart chart = new Chart
{
Width = 300,
Height = 300
};
Series series = new Series("Series" + i)
{
ChartType = SeriesChartType.Radar,
BorderWidth = 2
};
series.Points.AddXY("A", 83);
series.Points.AddXY("B", 64);
series.Points.AddXY("C", 95);
series.Points.AddXY("D", 76);
series.Points.AddXY("E", 57);
chart.Series.Add(series);
ChartArea chartArea = new ChartArea("ChartArea" + i);
if ((i & 0b100000) == 0)
chartArea.AxisX.MajorGrid.Enabled = false; // 隱藏 X 軸網格線
else
chartArea.AxisX.MajorGrid.Enabled = true; // 隱藏 X 軸網格線
if ((i & 0b010000) == 0)
chartArea.AxisY.MajorGrid.Enabled = false; // 隱藏 Y 軸網格線
else
chartArea.AxisY.MajorGrid.Enabled = true; // 隱藏 Y 軸網格線
if ((i & 0b001000) == 0)
chartArea.AxisY.MinorGrid.Enabled = false;
else
chartArea.AxisY.MinorGrid.Enabled = true;
if ((i & 0b000100) == 0)
chartArea.AxisX.MinorGrid.Enabled = false;
else
chartArea.AxisX.MinorGrid.Enabled = true;
if ((i & 0b000010) == 0)
chartArea.AxisX.LineWidth = 0; // 隱藏 X 軸線條
else
chartArea.AxisX.LineWidth = 1; // 隱藏 X 軸線條
if ((i & 0b000001) == 0)
chartArea.AxisY.LineWidth = 0; // 隱藏 Y 軸線條
else
chartArea.AxisY.LineWidth = 1; // 隱藏 Y 軸線條
chart.ChartAreas.Add(chartArea);
Label labelA = new Label
{
ID = "LabelA" + i
};
Label labelB = new Label
{
ID = "LabelB" + i
};
Label labelC = new Label
{
ID = "LabelC" + i
};
Label labelD = new Label
{
ID = "LabelD" + i
};
Label labelE = new Label
{
ID = "LabelE" + i
};
Label labelF = new Label
{
ID = "LabelF" + i
};
labelA.Text = "<br />i=" + i.ToString() + "<br />chartArea.AxisX.MajorGrid.Enabled = "
+ chartArea.AxisX.MajorGrid.Enabled.ToString() + "<br />";
labelB.Text = "chartArea.AxisY.MajorGrid.Enabled = " + chartArea.AxisY.MajorGrid.Enabled.ToString() + "<br />";
labelC.Text = "chartArea.AxisX.MinorGrid.Enabled = " + chartArea.AxisX.MinorGrid.Enabled.ToString() + "<br />";
labelD.Text = "chartArea.AxisY.MinorGrid.Enabled = " + chartArea.AxisY.MinorGrid.Enabled.ToString() + "<br />";
labelE.Text = "chartArea.AxisX.LineWidth = " + chartArea.AxisX.LineWidth.ToString() + "<br />";
labelF.Text = "chartArea.AxisY.LineWidth = " + chartArea.AxisY.LineWidth.ToString() + "<br />";
ChartPanel.Controls.Add(labelA);
ChartPanel.Controls.Add(labelB);
ChartPanel.Controls.Add(labelC);
ChartPanel.Controls.Add(labelD);
ChartPanel.Controls.Add(labelE);
ChartPanel.Controls.Add(labelF);
ChartPanel.Controls.Add(chart);
}
}
}
}
|
下圖
下圖下圖
下圖,看不出 AxisX.LineWidth = 1 的影響
********************************************************************************
相關
[研究]ASP.NET, WebForm, Chart 雷達圖測試(一)
2025-03-03
環境:Visual Studio 2019 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
把Chart拖入「設計」畫面,會註冊元件。
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1.Default" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<!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">
<asp:Chart ID="Chart1" runat="server" Width="600px" Height="500px">
<Titles>
<asp:Title Text="雷達圖 - 只顯示線條" Font="Arial, 14pt, style=Bold" />
</Titles>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" BorderColor="Blue" />
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisX LineColor="Black">
<MajorGrid LineColor="Transparent" />
</AxisX>
<AxisY LineColor="Black">
<MajorGrid LineColor="Transparent" />
</AxisY>
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Chart ID="Chart2" runat="server" Width="600px" Height="500px">
<Titles>
<asp:Title Text="雷達圖2 - 只顯示線條" Font="Arial, 14pt, style=Bold" />
</Titles>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" BorderColor="Blue" />
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisX LineColor="Black">
<MajorGrid LineColor="Transparent" />
</AxisX>
<AxisY LineColor="Black">
<%--<MajorGrid LineColor="Transparent" />--%>
</AxisY>
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Chart ID="Chart3" runat="server" Width="600px" Height="500px">
<Titles>
<asp:Title Text="雷達圖3" Font="Arial, 14pt, style=Bold" />
</Titles>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" BorderColor="Blue" />
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisX LineColor="Black">
<%--<MajorGrid LineColor="Transparent" />--%>
</AxisX>
<AxisY LineColor="Black">
<MajorGrid LineColor="Transparent" />
</AxisY>
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Chart ID="Chart4" runat="server" Width="600px" Height="500px">
<Titles>
<asp:Title Text="雷達圖4" Font="Arial, 14pt, style=Bold" />
</Titles>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" BorderColor="Blue" />
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
<AxisX LineColor="Black">
<%--<MajorGrid LineColor="Transparent" />--%>
</AxisX>
<AxisY LineColor="Black">
<%--<MajorGrid LineColor="Transparent" />--%>
</AxisY>
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Chart ID="Chart5" runat="server" Width="600px" Height="600px"
BorderlineWidth="1" BorderlineColor="Black" BorderlineDashStyle="Solid" Palette="None">
<Titles>
<asp:Title Text="雷達圖5" Font="Arial, 14pt, style=Bold" />
</Titles>
<ChartAreas>
<asp:ChartArea Name="ChartArea1" BackColor="Transparent">
<AxisX Interval="1">
<MajorGrid Enabled="False" />
</AxisX>
<AxisY Minimum="0" />
</asp:ChartArea>
</ChartAreas>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" Color="Blue"
BackGradientStyle="None" BackSecondaryColor="Transparent"
CustomProperties="AreaDrawingStyle=Polygon, DrawSideBySide=False"
IsValueShownAsLabel="true" LabelForeColor="Black" />
</Series>
</asp:Chart>
<asp:Chart ID="Chart6" runat="server" Width="600px" Height="600px"
BorderlineWidth="1" BorderlineColor="Black" BorderlineDashStyle="Solid" Palette="None">
<Titles>
<asp:Title Text="雷達圖6" Font="Arial, 14pt, style=Bold" />
</Titles>
<ChartAreas>
<asp:ChartArea Name="ChartArea1" BackColor="Transparent">
<AxisX Interval="1">
<MajorGrid Enabled="False" />
</AxisX>
<AxisY Minimum="0" />
</asp:ChartArea>
</ChartAreas>
<Series>
<asp:Series Name="Series1" ChartType="Radar" BorderWidth="2" BorderColor="Blue" Color="Transparent"
BackGradientStyle="None" BackSecondaryColor="Transparent"
CustomProperties="AreaDrawingStyle=Polygon, DrawSideBySide=False"
IsValueShownAsLabel="true" LabelForeColor="Black" />
</Series>
</asp:Chart>
</form>
</body>
</html>
|
Default.aspx.cs
using System;
using System.Drawing;
using System.Web.UI.DataVisualization.Charting;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GenerateRadarChart();
}
}
private void GenerateRadarChart()
{
// 設定 Series
Series series = Chart1.Series["Series1"];
series.ChartType = SeriesChartType.Radar;
series.BorderWidth = 2;
series.BorderColor = Color.Blue; // 設定線條顏色
series.Color = Color.Transparent; // 使填充透明
series.BackSecondaryColor = Color.Transparent; // 確保不會有漸層顏色
series.BackGradientStyle = GradientStyle.None; // 移除背景漸層
series.IsValueShownAsLabel = true; // 顯示數值標籤
// 加入資料點 (可根據需求修改)
series.Points.AddXY("A", 87);
series.Points.AddXY("B", 62);
series.Points.AddXY("C", 93);
series.Points.AddXY("D", 54);
series.Points.AddXY("E", 75);
series.Points.AddXY("A", 86); // 雷達圖需要閉合
// 設定 ChartArea (移除網格線、設定軸線)
ChartArea chartArea = Chart1.ChartAreas["ChartArea1"];
//chartArea.AxisX.MajorGrid.LineColor = Color.Transparent; // 隱藏 X 軸網格線
//chartArea.AxisY.MajorGrid.LineColor = Color.Transparent; // 隱藏 Y 軸網格線
Series series2 = Chart2.Series["Series1"];
// 加入資料點 (可根據需求修改)
series2.Points.AddXY("A", 87);
series2.Points.AddXY("B", 62);
series2.Points.AddXY("C", 93);
series2.Points.AddXY("D", 54);
series2.Points.AddXY("E", 75);
series2.Points.AddXY("A", 86); // 雷達圖需要閉合
series2.Color = Color.Transparent; // 使填充透明
Series series3 = Chart3.Series["Series1"];
// 加入資料點 (可根據需求修改)
series3.Points.AddXY("A", 87);
series3.Points.AddXY("B", 62);
series3.Points.AddXY("C", 93);
series3.Points.AddXY("D", 54);
series3.Points.AddXY("E", 75);
series3.Points.AddXY("A", 86); // 雷達圖需要閉合
Series series4 = Chart4.Series["Series1"];
// 加入資料點 (可根據需求修改)
series4.Points.AddXY("A", 87);
series4.Points.AddXY("B", 62);
series4.Points.AddXY("C", 93);
series4.Points.AddXY("D", 54);
series4.Points.AddXY("E", 75);
series4.Points.AddXY("A", 86); // 雷達圖需要閉合
Series series5 = Chart5.Series["Series1"];
// 加入資料點 (可根據需求修改)
series5.Points.AddXY("A", 87);
series5.Points.AddXY("B", 62);
series5.Points.AddXY("C", 93);
series5.Points.AddXY("D", 54);
series5.Points.AddXY("E", 75);
series5.Points.AddXY("A", 86); // 雷達圖需要閉合
Series series6 = Chart6.Series["Series1"];
// 加入資料點 (可根據需求修改)
series6.Points.AddXY("A", 87);
series6.Points.AddXY("B", 62);
series6.Points.AddXY("C", 93);
series6.Points.AddXY("D", 54);
series6.Points.AddXY("E", 75);
series6.Points.AddXY("A", 86); // 雷達圖需要閉合
}
}
}
|
下圖
********************************************************************************
相關