2024年4月30日 星期二

[研究]ASP.NET,試用 NReco.PdfGenerator 1.2.1 把 html 轉 pdf

[研究]ASP.NET,試用 NReco.PdfGenerator 1.2.1 把 html 轉 pdf

2024-04-30

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

NuGet Gallery | NReco.PdfGenerator 1.2.1
https://www.nuget.org/packages/NReco.PdfGenerator

Convert HTML to PDF in C#/.NET with NReco.PdfGenerator (FREE)
https://www.nrecosite.com/pdf_generator_net.aspx

線上說明
https://www.nrecosite.com/doc/NReco.PdfGenerator/

授權:1. Can I use PdfGenerator in my commercial project for FREE?

NReco.PdfGenerator can be used for FREE in .NET apps that have only one single-server production deployment.

A commercial license is required for:

  • Applications with multiple deployments, or one multi-server production deployment
  • SaaS apps

官方範例

Convert HTML to PDF in your C# code:

var htmlContent = String.Format("<body>Hello world: {0}</body>", 
		DateTime.Now);
var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter();
var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);

Create PDF from HTML file or URL:

htmlToPdf.GeneratePdfFromFile("http://www.nrecosite.com/", null, "export.pdf");  

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

NuGet 安裝 NReco.PdfGenerator 1.2.1 並沒有相依套件。

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;

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)
        {
			System.Text.StringBuilder html = new System.Text.StringBuilder();
			
			html.Append("<html>");
			html.Append("<head>");
			html.Append("<meta charset='utf-8' />");
			html.Append("<title>無標題文件</title>");
			html.Append(@"<style>
body {
	margin: 0px;
	padding: 0px;
}

.Paper {
	width: 1000px;
	margin-right: auto;
	margin-left: auto;
}
</style>"); html.Append("</head>");
			html.Append("<body>");
			html.Append("<div class='Paper'>");
			// h1 不可有「報名表」,否則產出的 .pdf 索引會變成「報吊表」
			//html.Append("<h1 style ='text-align:center'>報名表</h1>");
			// 若用 h1、h2、、等,產生的 .pdf 會有書籤定位點,「報名表」在書籤定位點會顯示成「報吊表」,故改用 div
			html.Append("<div style ='text-align:center; font-size:xx-large'>報名表</div>");

			string FName = "test.pdf";

			var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter();
			var pdfBytes = htmlToPdf.GeneratePdf(html.ToString());
			//Response給用戶端下載
			Response.Clear();
			Response.AddHeader("content-disposition", "attachment; filename=" + FName);//強制下載
			Response.ContentType = "application/octet-stream";
			Response.BinaryWrite(pdfBytes);
		}
	}
}




(完)

相關

[研究] Fedora 40 Workstation Linux 繁體中文版安裝

[研究] Fedora 40 Workstation Linux 繁體中文版安裝

2024-04-30

Fedora 40 於美國時間 2024-04-23釋出; EOL 於2025-05-13,壽命約1年。

官方網站、下載
https://getfedora.org/

Fedora version history - Wikipedia
https://en.wikipedia.org/wiki/Fedora_version_history

Fedora Linux Schedule
https://fedorapeople.org/groups/schedule/

下載
https://dl.fedoraproject.org/pub/fedora/linux/releases/39/Workstation/x86_64/iso/

Fedora (作業系統) - 維基百科,自由的百科全書
https://zh.wikipedia.org/wiki/Fedora_(%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1)

Fedora-Workstation-Live-x86_64-40-1.14.iso

2.13 GB (2,295,853,056 位元組)

Click圖片可看100%尺寸原圖,不難安裝,只是做個紀錄。

一開始安裝,畫面會自動跳到 1280x768 解析度,但安裝過程隨時可以調整解析度 ( 敝人在 VMware Workstaiton Pro的 VM 上安裝)













VMware Tools 顯示 ReInstall,疑似已經安裝了。


(完)

相關

[研究] Fedora 40 Workstation Linux 繁體中文版安裝
https://shaurong.blogspot.com/2024/04/fedora-40-workstation-linux.html

[研究] Fedora 39 Workstation Linux 繁體中文版安裝
https://shaurong.blogspot.com/2023/11/fedora-39-workstation-linux.html

[研究] Fedora 38 Workstation Linux 繁體中文版安裝
https://shaurong.blogspot.com/2023/04/fedora-38-workstation-linux.html

[研究] Fedora Server 37 Linux 繁體中文版安裝
https://shaurong.blogspot.com/2022/11/fedora-server-37-linux.html

[研究] Fedora 37 Workstation Linux 繁體中文版安裝
http://shaurong.blogspot.com/2022/11/fedora-37-workstation-linux.html

[研究] Fedora 34 Workstation Linux 安裝
http://shaurong.blogspot.com/2021/07/fedora-34-workstation-linux.html


[研究] Ubuntu 24.04 LTS Desktop Linux 安裝

[研究] Ubuntu 24.04 LTS Desktop Linux 安裝

2024-04-30

官方網站

https://www.ubuntu-tw.org/

https://releases.ubuntu.com/24.04/

22.04, 24.04 是 LTS 版,但 23.04和23.10 不是。

Click 圖片可以看100%原尺寸圖,安裝不難,只是留個紀錄。































(完)

相關

[研究] Ubuntu 24.04 LTS Desktop Linux 安裝
https://shaurong.blogspot.com/2024/04/ubuntu-2404-lts-desktop-linux.html

[研究] Ubuntu 23.10 (非LTS) Desktop Linux 安裝
https://shaurong.blogspot.com/2023/11/ubuntu-2310-lts-desktop-linux.html

[研究] Ubuntu 23.04 (非LTS) Desktop Linux 安裝
http://shaurong.blogspot.com/2023/04/ubuntu-2304-lts-desktop-linux.html

[研究] Ubuntu 22.10 Desktop Linux 安裝
https://shaurong.blogspot.com/2022/10/ubuntu-2210-desktop-linux.html

[研究] Ubuntu 18.04 Desktop x64 LTS 安裝 VMware Tools-10.2.5-8068393.tar.gz
https://shaurong.blogspot.com/2018/05/ubuntu-1804-desktop-x64-lts-vmware.html

[研究] Ubuntu 22.04 LTS Desktop Linux 安裝
https://shaurong.blogspot.com/2022/05/ubuntu-2210-lts-desktop-linux.html

[研究] Ubuntu 21.10 Desktop Linux 安裝
https://shaurong.blogspot.com/2021/10/ubuntu-2110-desktop-linux.html

[研究] Ubuntu 21.04 Live Server Linux 安裝
https://shaurong.blogspot.com/2021/07/ubuntu-2104-live-server-linux.html

Index of /ubuntu-releases/
https://ftp.ubuntu-tw.org/ubuntu-releases/

Ubuntu release cycle | Ubuntu
https://ubuntu.com/about/release-cycle

BionicBeaver/ReleaseSchedule - Ubuntu Wiki
https://wiki.ubuntu.com/BionicBeaver/ReleaseSchedule

Releases - Ubuntu Wiki
https://wiki.ubuntu.com/Releases

2024年4月29日 星期一

[研究][ASP.NET]RestSharp 106.15相依套件測試

[研究][ASP.NET]RestSharp 106.15相依套件測試

2023-04-29

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

最近一次更新元件,發現 RestSharp 相依套件數量似乎很多,建立一個新的、空的方案測試看看,考慮是否換掉它,改用微軟提供的 HTTPClient,或微軟更新提供的 HttpClientFactory   (Microsoft 已經棄用WebClient)。

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

WebApplication1

正在安裝:

RestSharp.106.15.0

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

(完)

相關

2024年4月28日 星期日

[研究]Chrome出現 "無法開啟這個網頁"

[研究]Chrome出現 "無法開啟這個網頁"

2024-04-28

剛剛瀏覽FB網站,卻出現錯誤,相同網址,另一台正常。請除瀏覽器Cache,依然異常。Reboot Windows 後,正常了。

無法開啟這個網頁
https://support.google.com/chrome/answer/95669

修復“噢,啪!”頁面崩潰和其他頁面載入錯誤
Fix "Aw, Snap!" page crashes and other page loading errors
https://support.google.com/chrome/answer/95669?visit_id=638498592968465075-2832401098&p=e_awsnap_rl&rd=1




(完)

2024年4月27日 星期六

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 HttpClient 做 Restful API 呼叫(二)verify

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 HttpClient 做 Restful API 呼叫(二)verify

2024-04-27、2024-05-16

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

因 RestSharp 於 2009 年首次推出,成為 .NET 開發者中非常受歡迎的一個選擇。在 RestSharp v107 開始,語法大改;而 .NET Framework 4.5 (2012 年推出) 開始提供 HttpClient,考慮改用這個。

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

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="IRESTfulServerUrl" value="https://網址/" />
    <add key="IRESTfulAccount" value="帳號" />
    <add key="IRESTfulPassword" value="密碼" />
  </appSettings>
</configuration>



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

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Net.Http;	// NuGet 安裝,HttpClient 要使用
using System.Threading.Tasks;

namespace WebApplication1
{

    public class VerifyResult
    {
        public string message { get; set; }
        public string describe { get; set; }

        // RestSharp v106 要這樣才能運作
        //public List<VerifyData> data { get; set; }

        // RestSharp v107 開始或 HttpClient ,要這樣才能運作
        public VerifyData data { get; set; }
    }

    public class VerifyData
    {
        public string product_class { get; set; }
        public string product_account { get; set; }
        public string product_name { get; set; }
        public string contact_account { get; set; }
        public string contact_name { get; set; }
        public string contact_cellphone { get; set; }
        public string contact_mail { get; set; }
        public string contact_dept { get; set; }
        public string contact_tel { get; set; }
        public string contact_extend { get; set; }
        public string contact_title { get; set; }
        public string status { get; set; }
        public List<string> contact_category { get; set; }
    }
    public partial class Default : System.Web.UI.Page
    {
        protected async void Page_Load(object sender, EventArgs e)
        {
            string account = "略";
            string password = "略";


            VerifyResult content = new VerifyResult();
            content = await Verify_by_HttpClient("1", account, password);
        }

        #region === public async static VerifyResult Verify_by_HttpClient(string account_type, string account, string password) ===
        public async static Task<VerifyResult> Verify_by_HttpClient(string account_type, string account, string password)
        {
            string iRESTfulUrl = ConfigurationManager.AppSettings["IRESTfulUrl"];
            string iRESTfulSysId = ConfigurationManager.AppSettings["IRESTfulSysId"];
            string iRESTfulSysPass = ConfigurationManager.AppSettings["IRESTfulSysPass"];
			string acc = TextBox_Acc.Text.Trim();
			string pass = TextBox_Pass.Text.Trim();
			
            var httpClient = new HttpClient();
            try
            {
//----------------------------------------------------
// 2024-05-16 補,發現回傳的 VerifyResult,如果成功 (0001) 和不成功的格式不同,VerifyData 是 [],
// 不成功的 在 VerifyResult v = serializer.Deserialize<VerifyResult>(jsonTextReader); 會出錯
/*
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'WebApplication1.Models.VerifyData' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. 
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. 
JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path 'data', line 1, position 68.
*/
// 只好做一個符合格式的
// 此問題在以前用 RestSharp v106 不會有
#region === 1 ===

var requestBody2 = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("sysid", iRESTfulSysId), new KeyValuePair<string, string>("syspass", iRESTfulSysPass), new KeyValuePair<string, string>("acc", acc), new KeyValuePair<string, string>("pass", pass), });
var response2 = await httpClient.PostAsync(WS_URL + "restful/verify", requestBody2);
                bool isSuccessStatusCode2 = response2.IsSuccessStatusCode;
                HttpResponseMessage ensureSuccessStatusCode2 = new HttpResponseMessage();
                if (isSuccessStatusCode2 == false)
                {
                    ensureSuccessStatusCode2 = response2.EnsureSuccessStatusCode();
                }

                var responseStream2A = response2.Content.ReadAsStreamAsync().Result;
                using (var responseStream2B = await response2.Content.ReadAsStreamAsync())
                {
                    using (StreamReader streamReader2B = new StreamReader(responseStream2B))
                    using (Newtonsoft.Json.JsonTextReader jsonTextReader2B = new Newtonsoft.Json.JsonTextReader(streamReader2B))
                    {
                        var json = streamReader2B.ReadToEnd(); // 讀取 JSON 資料到字串中
                        var jsonObject = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
                        string message = jsonObject.message;
                        
                        if (message !="0001")
                        {
                            VerifyResult vv = new VerifyResult();
                            vv.message = message;
                            return vv;
                        }
                    }
                }
                #endregion
//----------------------------------------------------
var requestBody = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair<string, string>("sysid", iRESTfulSysId),
                    new KeyValuePair<string, string>("syspass", iRESTfulSysPass),
                    new KeyValuePair<string, string>("acc", acc),
                    new KeyValuePair<string, string>("pass", pass),
                });                var response2 = await httpClient.PostAsync(WS_URL + "restful/verify", requestBody);

var response = await httpClient.PostAsync(iRESTfulUrl + "restful/verify", requestBody); bool isSuccessStatusCode = response.IsSuccessStatusCode; HttpResponseMessage ensureSuccessStatusCode = new HttpResponseMessage(); if (isSuccessStatusCode == false) { ensureSuccessStatusCode = response.EnsureSuccessStatusCode(); } var responseStream2 = response.Content.ReadAsStreamAsync().Result; using (var responseStream = await response.Content.ReadAsStreamAsync()) { using (StreamReader streamReader = new StreamReader(responseStream)) using (Newtonsoft.Json.JsonTextReader jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) { //不可以同時 ReadToEnd 和 Deserialize,只能擇一使用 //var json = streamReader.ReadToEnd(); // 讀取 JSON 資料到字串中 var serializer = new Newtonsoft.Json.JsonSerializer(); //return serializer.Deserialize<VerifyResult>(jsonTextReader); VerifyResult v = serializer.Deserialize<VerifyResult>(jsonTextReader); return v; } } } catch (HttpRequestException ex) { string exMsg = ""; if (ex != null) exMsg = ex.Message.ToString(); throw; } } #endregion } }

Default.aspx

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

...(略)

實際測試,在 Visual Studio 中 Debug,v確實有拿到回傳資料。

(完)

相關

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 HttpClient 做 Restful API 呼叫(二)verify
https://shaurong.blogspot.com/2024/04/aspnetwebform-restsharp-10615_27.html

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 HttpClient 做 Restful API 呼叫(一)
https://shaurong.blogspot.com/2024/04/aspnetwebform-restsharp-10615.html

[研究]ASP.NET,使用 HttpClient 時 using System.Net.Http; 編譯出錯:System.Net' 中沒有類型或命名空間名稱 'Http' (是否遺漏了組件參考?)
https://shaurong.blogspot.com/2024/04/aspnetsystemnet-http.html

RestSharp Next (v107) | RestSharp
https://restsharp.dev/v107/#restsharp-v107

NuGet Gallery | RestSharp
https://www.nuget.org/packages/RestSharp/

RestSharp - Simple .NET REST Client - GitHub
https://github.com/restsharp/RestSharp

[研究][ASP.NET WebForm C#]Newtonsoft.Json 13.0.1 序列化、反序列化測試https://shaurong.blogspot.com/2022/02/aspnet-webform-cnewtonsoftjson-1301.html

[研究][ASP.NET WebForm C#]HttpClient 呼叫 Web API、REST/RESTful API 測試(二)
https://shaurong.blogspot.com/2022/02/aspnet-webform-chttpclient-web_26.html

[研究][ASP.NET WebForm C#]HttpClient 呼叫 Web API、REST/RESTful API 測試(一)
http://shaurong.blogspot.com/2022/02/aspnet-webform-chttpclient-web.html

[研究][ASP.NET WebForm C#]WebClient 呼叫 Web API、REST/RESTful API 測試https://shaurong.blogspot.com/2022/02/aspnet-webform-cwebclient-web.html



[研究]BT (.torremt、磁力) 下載工具比較

[研究]BT (.torremt、磁力) 下載工具比較

2024-04-27

比較 μTorrent (uTorrent), qBittorrent, Deluge, Transmission, BitComet 特點 ? 優點 ? 缺點 ? 佔有率 ? 用表格比較

ChatGPT

工具名稱特點優點缺點佔有率
μTorrent (uTorrent)簡潔的介面,快速的下載速度。- 輕量級,佔用系統資源少。
- 提供豐富的功能,如排程、RSS 訂閱。
- 曾因廣告和安全問題受到爭議。高(約佔 50%)
qBittorrent開源、跨平台,提供豐富的功能。- 提供排程、RSS 訂閱、IP 過濾器等功能。
- 界面簡潔易用。
- 某些高級功能可能不如其他客戶端完善。中(約佔 20%)
Deluge開源、模組化,支援插件系統。- 輕量級,跨平台,支援多種插件擴展功能。
- 界面簡單直觀。
- 可能缺乏某些高級功能。中(約佔 15%)
Transmission簡潔、輕量級,適合資源有限的系統。- 資源消耗低,適合用於舊式電腦或資源有限的系統。
- 界面簡單清爽。
- 功能相對基本,缺乏某些高級功能。中(約佔 10%)
BitComet具有內置的 P2P 文件分享功能,支援多線程下載。- 提供多線程下載、快速種子搜尋等功能。
- 內置 P2P 文件分享功能。
- 曾因廣告、隱私問題等受到批評。低(約佔 5%)

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

Copilot

特點μTorrent (uTorrent)qBittorrentDelugeTransmissionBitComet
輕量級
跨平台支援
加密功能
WebUI
插件系統
長效種子
磁盤緩存
邊下載邊播放
佔有率未提供具體數值未提供具體數值未提供具體數值未提供具體數值未提供具體數值

(完)

相關

[研究]ASP.NET,Response.Redirect沒執行,錯誤訊息 "執行緒已經中止。"

[研究]ASP.NET,Response.Redirect沒執行,錯誤訊息 "執行緒已經中止。"

2024-04-27

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

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


執行緒已經中止。

ERRORSHELPABOUT

System.Threading.ThreadAbortException

執行緒已經中止。


System.Threading.ThreadAbortException: 執行緒已經中止。

   於 System.Web.HttpContext.InvokeCancellableCallback(WaitCallback callback, Object state)

   於 System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action)

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

GPT-4 Copilot

您遇到的問題是 ASP.NET 中的一個常見情況。當使用 Response.Redirect 或 Server.Transfer 時,內部會調用 Response.End,而這會中止正在執行的線程。為了解決這個問題,您可以採取以下兩種方法之一:

1.使用 HttpContext.Current.ApplicationInstance.CompleteRequest():

在使用 Server.Transfer 時,您可以使用 Server.Execute 作為替代方法。這樣可以避免 ThreadAbortException。

例如:


Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();   

這樣,您可以告訴 IIS 管道在返回控制後直接進入 EndRequest 階段。

2.使用 Response.Redirect 的多載方法:

使用多載方法 Response.Redirect(string url, bool endResponse),將 endResponse 參數設置為 false。

這樣可以隱藏對 Response.End 的內部調用。

例如:


Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();   

這樣不會引發 ThreadAbortException,但您需要負責在事件處理程序中提前返回控制,以避免其他代碼的執行。

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

結果 Elmah 雖然沒有報告問題,但是 Response.Redirect 無效,不太清楚外包商如何搞的,這個方案某些地方用 Response.Redirect 就是無效,外包商自己到處都是用 Response.Write,而非用 Response.Redirect。

後來用 Response.Write 代替 Response.Redirect 重導網址


Response.Write("<script>window.location='WebForm1.aspx';</script>");  

成功。


註:下面方法或可考慮(尚未實際測試)

Response.Write("<script>window.open('WebForm1.aspx', '_blank');</script>");

Response.Write("<script>window.location.href = 'WebForm1.aspx';</script>");

(完)

相關

2024年4月24日 星期三

[研究][C#]整數轉 Excel 橫列標題 26進位轉換

[研究][C#]整數轉 Excel 橫列標題 26進位轉換

2024-04-24

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

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

Excel的橫列標題是 A,B,C, ... Z, AA, AB, .... 依此類推,

10進位 => 26進位 ( 0->A, 1->B, ....)

using System;

class Program
{
    static string ConvertToBase26(int number)
    {
        const string base26Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        string result = string.Empty;

        do
        {
            result = base26Chars[number % 26] + result;
            number /= 26;
        } while (number-- > 0);

        return result;
    }

    static void Main()
    {
        int number = 12345;
        string base26 = ConvertToBase26(number);
        Console.WriteLine($"Number {number} in base 26 is {base26}");
    }
}



26進位 => 10進位


using System;

class Program
{
    static int ConvertFromBase26(string base26)
    {
        const string base26Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int result = 0;

        for (int i = 0; i < base26.Length; i++)
        {
            result = result * 26 + base26Chars.IndexOf(base26[i]);
        }

        return result;
    }

    static void Main()
    {
        string base26 = "BCDE";
        int number = ConvertFromBase26(base26);
        Console.WriteLine($"Base 26 number {base26} is {number} in base 10");
    }
}




(完)

相關

2024年4月23日 星期二

[研究]ASP.NET,用 NuGet 安裝 ckeditor-full 4.22.1 會安裝那些套件

[研究]ASP.NET,用 NuGet 安裝 ckeditor-full 4.22.1 會安裝那些套件

2024-04-23

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

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

WebApplication1

正在安裝:

ckeditor-full.4.22.1

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

其實目的不是安裝,是移除後,瞭解一下,還有那些被 ckeditor順便安裝的相依套件,是否可以移除。

(完)

相關

2024年4月22日 星期一

[研究]比較 Newtonsoft.Json.JsonConvert、System.Text.Json、DataContractJsonSerializer

[研究]比較 Newtonsoft.Json.JsonConvert、System.Text.Json、DataContractJsonSerializer

2024-04-22

比較支援環境、特點、優點、缺點

Newtonsoft.Json.JsonConvert

System.Text.Json

DataContractJsonSerializer

ChatGPT

這三個是在C#中用於處理JSON序列化和反序列化的常見工具。以下是它們的比較:

Newtonsoft.Json.JsonConvert

支援環境: 適用於.NET Framework和.NET Core。

特點:

  • 提供了廣泛的自定義選項,如自定義序列化和反序列化行為、忽略屬性、自訂轉換器等。
  • 較高的性能和廣泛的功能。

優點:

  • 社區支持良好,文檔豐富,用戶數量眾多。
  • 擁有豐富的功能和選項,適用於各種場景。

缺點:

  • 相對於.NET Core內置的System.Text.Json,需要額外的依賴。
  • 在一些情況下可能會導致較大的組件大小。

System.Text.Json

支援環境: .NET Core 3.0及以上版本和.NET 5.0及以上版本。

特點:

  • 是.NET Core和.NET 5中的內置JSON處理庫,無需額外安裝。
  • 提供了基本的JSON序列化和反序列化功能,並提供了一些基本的自定義選項。

優點:

  • 由Microsoft開發和維護,與.NET平台整合緊密。
  • 較小的組件大小和更快的序列化/反序列化速度,特別是對於大型數據量。

缺點:

  • 功能相對較少,對於高度定制化的需求可能不足。

DataContractJsonSerializer

支援環境: 適用於.NET Framework。

特點:

  • 通過DataContract屬性來指定需要序列化的類型成員。
  • 依賴於.NET Framework的DataContract屬性,用於定義序列化和反序列化的規則。

優點:

  • 內置於.NET Framework中,無需額外安裝。
  • 適用於一些遺留應用程序或者需要與現有DataContract相集成的場景。

缺點:

  • 功能較為基本,自定義選項有限。
  • 對於新的.NET Core或.NET 5應用程序不適用,因為它只能在.NET Framework中使用。

總體來說,根據您的具體需求和環境,您可以選擇適合的JSON處理工具。如果您在.NET Core或.NET 5應用程序中工作,並且需要快速且輕量級的JSON處理,則System.Text.Json可能是更好的選擇。如果您需要豐富的功能和廣泛的社區支持,則Newtonsoft.Json可能更合適。而如果您在使用遺留的.NET Framework應用程序,則可以考慮使用DataContractJsonSerializer。

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

特性Newtonsoft.JsonSystem.Text.JsonDataContractJsonSerializer
支援環境支援 .NET Framework 和 .NET Core支援 .NET Core 和 .NET 5+支援 .NET Framework 和 .NET Core
特點- 彈性高,可序列化幾乎所有.NET類型
- 支援 LINQ to JSON
- 容錯性強
- 擴展性佳
- 內建於 .NET Core 和 .NET 5+
- 性能優異
- 輕量級
- 支援部分 JSON Schema 標準
- 內建於 .NET Framework
- 可與 WCF 集成
- 支援部分 JSON Schema 標準
優點- 彈性高,可處理各種情況
- 社區支援豐富
- 擴展性強
- 設定彈性
- 效能較好
- 內建於 .NET 平台
- 簡潔易用
- 安全性高
- 內建於 .NET 平台
- 可與 WCF 集成
- 整合性高
缺點- 性能較差
- 依賴較多外部套件
- 部分功能不如 Newtonsoft.Json
- 彈性較差
- 彈性較差
- 效能較差
- 可定制性不足


********************************************************************************
User

.NET Framework 為何內建提供 DataContractJsonSerializer 又內建提供  System.Text.Json ? 兩者差異 ?

ChatGPT

.NET Framework 內建提供了 DataContractJsonSerializer 和 .NET Core 之後的版本內建提供了 System.Text.Json 主要是因為這兩個工具在設計和使用上有一些差異,以及針對不同的需求和場景。

差異:

性能和效能:
  • DataContractJsonSerializer 在處理大量數據時效能較差,而 System.Text.Json 則在這方面表現更佳,特別是在處理大型 JSON 數據時。
彈性和功能:
  • DataContractJsonSerializer 主要是為了支援 WCF (Windows Communication Foundation) 和舊版 .NET 框架的需求而設計,它的彈性較差,且支援的功能相對較少。
  • System.Text.Json 則是在 .NET Core 和 .NET 5+ 中內建的 JSON 序列化工具,它提供了更多的彈性和功能,例如支援序列化和反序列化的擴展點、自定義序列化器等。
生態系統和支援:
  • 隨著 .NET Core 和 .NET 5+ 的發展,.NET Core 生態系統越來越強大,System.Text.Json 作為內建的 JSON 序列化工具受到了廣泛的支援和應用,並且有著活躍的社區支持。
  • 相比之下,DataContractJsonSerializer 主要是在舊版 .NET Framework 中使用,雖然在舊版框架中仍然受到支援,但是它的發展和更新相對較少。
總的來說,.NET Core 以及之後的版本提供了 System.Text.Json 主要是為了提高 JSON 序列化的性能和彈性,並且符合現代應用開發的需求,而 DataContractJsonSerializer 則主要是為了舊版 .NET Framework 和 WCF 的相容性考慮。

(完)

[研究]ASP.NET, RestSharp v106, v107, v108, v109, v110, v111,v112 程式寫法差異?

[研究]ASP.NET, RestSharp v106, v107, v108, v109, v110, v111,v112 程式寫法差異?

2024-04-22

ASP.NET,WebForm, 請說明 RestSharp  v106, v107, v108, v109, v110, v111,v112 程式寫法差異?

Copilot

v106:

  • v106 的變更相對較少,並且在程式碼簽名上並未造成破壞性。如果您使用的是這個版本,您可以繼續使用相同的程式寫法。
  • 請注意,v106 是較早的版本,因此如果您打算升級,建議您閱讀後續版本的變更。

v107:

  • v107 是一個重大的升級,其中包含了一些破壞性的變化。
  • 最重要的變化是,RestSharp 不再使用過時的 HttpWebRequest 類別,而改用廣泛使用的 HttpClient。這個改變解決了許多問題,例如因不正確的 HttpClient 實例緩存而導致的連接中斷、更新的協議支援等。
  • SimpleJson 從程式碼庫中完全移除。取而代之,RestSharp 現在使用 System.Text.Json 套件中的 JsonSerializer,這是 ASP.NET Core 的預設序列化程式。
  • 大部分介面已經被移除。現在您將使用 RestClient 類別實例,而大部分客戶端選項已經移到 RestClientOptions 中。

v108、v109、v110、v111、v112:

  • v108 到 v112 的程式碼變更在簽名上並不會造成破壞性,但 v110 與之前的版本不具有二進制兼容性。主要差異在於 DefaultParameters 集合現在在所有變更操作時都會使用鎖定。
  • v109 引入了 IRestClient 介面,但新介面的 API 比之前的版本要小得多。您將使用 RestClient 類別實例,而大部分客戶端選項已經移到 RestClientOptions 中。

總之,如果您正在使用 RestSharp,請確保遵循最新版本的建議和指南,以確保程式碼的正確性和效能。

https://restsharp.dev/v107/#restsharp-v107

https://github.com/restsharp/RestSharp/releases

https://restsharp.dev/intro.html#content-type

(完)

相關

[研究]ASP.NET,WebForm,將 RestSharp 106.15 升級 RestSharp 110.2.0 做 Restful API 呼叫

[研究]ASP.NET,WebForm,將 RestSharp 106.15 升級 RestSharp 110.2.0 做 Restful API 呼叫

[研究][ASP.NET]用 RestSharp v107 做 RESTful API 呼叫(四)將 RestSharp 106.15 升級 RestSharp 110.2.0 

2024-04-22

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

因 RestSharp 在 v107 開始,語法大改。而且 v107 至 110.2.0,疑似陸續有改,之前研究測試的 Code 部分不能用。

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

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="IRestfulServerUrl" value="https://網址/" />
    <add key="IRestfulAccount" value="帳號" />
    <add key="IRestfulPassword" value="密碼" />
  </appSettings>
</configuration>


Models\MyModel.cs

保留不公開


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

Default.aspx

using RestSharp;    // NuGet 安裝 RestSharp 106.15
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Net.Http;    // HttpClient 使用
using System.Threading.Tasks;
using WebApplication1.Models;   // 自己寫的

namespace WebApplication1
{
    public class IRestfulClient
    {
        static readonly string IRestfuleServerURL = ConfigurationManager.AppSettings["IRestfulServerUrl"];
        static readonly string IRestfulAccount = ConfigurationManager.AppSettings["IRestfulAccount"];
        static readonly string IRestfulPassword = ConfigurationManager.AppSettings["IRestfulPassword"];

       ...(略)
/* 註解,v106 和 v107 無法共存 public static ProductListResult getProductList() { var client = new RestClient(IRestfuleServerURL + "rest/getProductList"); var request = new RestRequest(Method.POST); RestResponse<ProductListResult> response2; request.AddParameter("acc", IRestfulAccount); request.AddParameter("pass", IRestfulPassword); try { response2 = (RestSharp.RestResponse<ProductListResult>)client.Execute<ProductListResult>(request); } catch (Exception) { throw; } return response2.Data; } */ public static async Task<ProductListResult> getProductList_by_HttpClient()
{ var httpClient = new HttpClient(); try { var requestBody = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("acc", IRestfulAccount), new KeyValuePair<string, string>("pass", IRestfulPassword) }); var response = await httpClient.PostAsync(IRestfuleServerURL + "rest/getProductList", requestBody);
response.EnsureSuccessStatusCode(); using (var responseStream = await response.Content.ReadAsStreamAsync()) { using (var streamReader = new StreamReader(responseStream)) using (var jsonReader = new Newtonsoft.Json.JsonTextReader(streamReader)) { var serializer = new Newtonsoft.Json.JsonSerializer(); return serializer.Deserialize<ProductListResult>(jsonReader); } } } catch (HttpRequestException) { throw; } } public static async Task<ProductListResult> getProductList_by_RestSharp107() { // 以 Postman 測試時,參數是加在 Body 才行, // 但在本程式用 AddBody 收不到參數,要用 AddParamter 才行 var client = new RestClient(IRestfuleServerURL + "rest/getProductList"); //var request = new RestRequest(Method.POST); //RestResponse<ProductListResult> response; var request = new RestRequest() .AddHeader("Content-Type", "application/x-www-form-urlencoded") .AddParameter("code", IRestfulAccount) .AddParameter("sys_pass", IRestfulPassword); try { //response2 = (RestSharp.RestResponse<ProductListResult>)client.Execute<ProductListResult>(request); var response = await client.PostAsync<ProductListResult>(request); var json = Newtonsoft.Json.JsonConvert.SerializeObject(response); //ProductListResult responseUnitListResultJson = Newtonsoft.Json.JsonConvert.DeserializeObject<ProductListResult>(responseVerifyResultString); //var responseVerifyResultString = await response.data.ReadAsStringAsync(); ProductListResult responseUnitListResultJson = Newtonsoft.Json.JsonConvert.DeserializeObject<ProductListResult>(json); //var responseMessage = response.message; //var responseData = response.data; //var responseDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(responseData); //ProductListData productListData = Newtonsoft.Json.JsonConvert.DeserializeObject <ProductListData>(responseDataJson);//Error return responseUnitListResultJson;
//if (response.IsSuccessStatusCode) //{ // var responseVerifyResultString = await response.Content.ReadAsStringAsync(); // ProductListResult responseProductListResultJson = Newtonsoft.Json.JsonConvert.DeserializeObject<ProductListResult>(responseVerifyResultString); // return responseProductListResultJson; //} //else //{ // return null; //} /* // 發送請求並取得回應 //---------------------------------------- RestResponse response0 = client.Execute(request); //Response.Write(response0.Content+ "<br /><br />"); //成功 //var json0 = JsonConvert.SerializeObject(response0); //Response.Write("Json0: " +json0+"<br /><br />"); // Fail Message //---------------------------------------- var response1 = await client.PostAsync<ProductListResult>(request); //Response.Write(response.message); var json1 = Newtonsoft.Json.JsonConvert.SerializeObject(response); //Response.Write("Json : " + json+ "<br /><br />"); // 成功 //---------------------------------------- var response2 = await client.ExecuteAsync<ProductListResult>(request); //Response.Write("response2.Data.message : " + response2.Data.message+ "<br /><br />"); // 成功 //---------------------------------------- var response3 = await client.ExecutePostAsync<ProductListResult>(request); //Response.Write(response.message); var json3 = Newtonsoft.Json.JsonConvert.SerializeObject(response3); //Response.Write("Json3 : " + json3+ "<br /><br />"); // 成功 //---------------------------------------- var response4 = await client.PostAsync(request); //Response.Write(response.message); var json4 = Newtonsoft.Json.JsonConvert.SerializeObject(response4); //Response.Write("Json4 : " + json4+ "<br /><br />"); // 成功,但額外多一些怪資訊,因為沒有 Object 的 class //---------------------------------------- var response5 = await client.PostAsync<GetObjectResult>(request); //Response.Write(response.message); var json5 = Newtonsoft.Json.JsonConvert.SerializeObject(response5); //Response.Write("Json5 : " + json5 + "<br /><br />"); // 成功 //---------------------------------------- */ } catch (Exception) { throw; } //return response2.Data;
} ...(略) } }

Default.aspx

<%@ Page Async="true" 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="用 RestSharp v106 呼叫 Restful API" OnClick="Button1_Click" /><br />--%>
        <asp:Button ID="Button2" runat="server" Text="用 HttpClient 呼叫 Restful API" OnClick="Button2_Click" /><br />
        <asp:Button ID="Button3" runat="server" Text="用 RestSharp 110.2.0 呼叫 Restful API" OnClick="Button3_Click" /><br />
        <asp:Label ID="Label_MSG1" runat="server"></asp:Label><br />
    </form>
</body>
</html>



Default.aspx.cs

using System;
using System.Net.Http;  // 要用 NuGet 安裝
using WebApplication1.Models;   // IRestfulClient 使用的 Client

namespace WebApplication1
{
    public partial class Default : System.Web.UI.Page
    {
        public static readonly HttpClient client = new HttpClient();
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /* RestSharp 106 和 RestSharp v107 無法共存
        protected void Button1_Click(object sender, EventArgs e)
        {
            Label_MSG1.Text = "";
            ProductListResult content = new ProductListResult();
            try
            {
                content = IRestfulClient.getProductList();
                Label_MSG1.ForeColor = System.Drawing.Color.Green;
                Label_MSG1.Text = DateTime.Now.ToString() + " RestSharp 106.15 執行成功。";
            }
            catch (Exception ex)
            {
                //throw;
                Label_MSG1.ForeColor = System.Drawing.Color.Red;
                if (ex != null)
                {
                    Label_MSG1.Text = ex.Message.ToString();
                }
                else
                {
                    Label_MSG1.Text = "不明錯誤。";
                }
            }
        }
        */

        protected async void Button2_Click(object sender, EventArgs e)
        {
            Label_MSG1.Text = "";
            ProductListResult content = new ProductListResult();
            try
            {
                content = await IRestfulClient.getProductList_by_HttpClient();
                Label_MSG1.ForeColor = System.Drawing.Color.Green;
                Label_MSG1.Text = DateTime.Now.ToString() + " HttpClient 執行成功。";
            }
            catch (Exception ex)
            {
                //throw;
                Label_MSG1.ForeColor = System.Drawing.Color.Red;
                if (ex != null)
                {
                    Label_MSG1.Text = ex.Message.ToString();
                }
                else
                {
                    Label_MSG1.Text = "不明錯誤。";
                }
            }
        }

        // RestSharp v107 開始寫法大改
        protected async void Button3_Click(object sender, EventArgs e)
        {
            Label_MSG1.Text = "";
            ProductListResult content = new ProductListResult();
            try
            {
                content = await IRestfulClient.getProductList_by_RestSharp107();
                Label_MSG1.ForeColor = System.Drawing.Color.Green;
                Label_MSG1.Text = DateTime.Now.ToString() + " RestSharp 110.2.0 執行成功。";
            }
            catch (Exception ex)
            {
                //throw;
                Label_MSG1.ForeColor = System.Drawing.Color.Red;
                if (ex != null)
                {
                    Label_MSG1.Text = ex.Message.ToString();
                }
                else
                {
                    Label_MSG1.Text = "不明錯誤。";
                }
            }
        }
    }
}




(完)

相關

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 RestSharp 110.2.0 做 Restful API 呼叫
[研究][ASP.NET]用 RestSharp v107 做 RESTful API 呼叫(四)將 RestSharp 106.15 升級 RestSharp 110.2.0
https://shaurong.blogspot.com/2024/04/aspnetwebform-restsharp-10615-restsharp.html

[研究]ASP.NET,WebForm,將 RestSharp 106.15 改用 HttpClient 做 Restful API 呼叫https://shaurong.blogspot.com/2024/04/aspnetwebform-restsharp-10615.html

[研究]ASP.NET,使用 HttpClient 時 using System.Net.Http; 編譯出錯:System.Net' 中沒有類型或命名空間名稱 'Http' (是否遺漏了組件參考?)
https://shaurong.blogspot.com/2024/04/aspnetsystemnet-http.html

RestSharp Next (v107) | RestSharp
https://restsharp.dev/v107/#restsharp-v107

NuGet Gallery | RestSharp
https://www.nuget.org/packages/RestSharp/

RestSharp - Simple .NET REST Client - GitHub
https://github.com/restsharp/RestSharp

[研究][ASP.NET WebForm C#]Newtonsoft.Json 13.0.1 序列化、反序列化測試https://shaurong.blogspot.com/2022/02/aspnet-webform-cnewtonsoftjson-1301.html

[研究][ASP.NET WebForm C#]HttpClient 呼叫 Web API、REST/RESTful API 測試(二)
https://shaurong.blogspot.com/2022/02/aspnet-webform-chttpclient-web_26.html

[研究][ASP.NET WebForm C#]HttpClient 呼叫 Web API、REST/RESTful API 測試(一)
http://shaurong.blogspot.com/2022/02/aspnet-webform-chttpclient-web.html

[研究][ASP.NET WebForm C#]WebClient 呼叫 Web API、REST/RESTful API 測試https://shaurong.blogspot.com/2022/02/aspnet-webform-cwebclient-web.html