徹底掌握.NET中序列化反序列化問題及避坑指南
在 .NET 領(lǐng)域,序列化(Serialization)簡單來說就是把對象“拍扁”成一段數(shù)據(jù)流(如二進制、XML、JSON),以便存到硬盤或通過網(wǎng)絡(luò)發(fā)給別人。反序列化(Deserialization)則是把這段流“吹氣”還原成內(nèi)存里的 C# 對象。
序列化是把一個內(nèi)存中的對象的信息轉(zhuǎn)化成一個可以持久化保存的形式,以便于保存或傳輸,序列化的主要作用是不同平臺之間進行通信,常用的有序列化有json、xml、文件等,下面就逐個講下這三種序列化的方法。
在 C# 開發(fā)中,你主要會接觸到以下三種類型的序列化方式:

注意:原生的 BinaryFormatter 因為存在嚴(yán)重的安全漏洞,微軟已經(jīng)在 .NET 5+ 以后將其標(biāo)注為過時(Deprecated),千萬不要在生產(chǎn)環(huán)境使用它。
對象的序列化主要有兩種用途
1.把對象的字節(jié)序列永久地保存到硬盤上,通常存放在一個文件中
我們經(jīng)常需要將對象的字段值保存到磁盤中,并在以后檢索此數(shù)據(jù)。盡管不使用序列化也能完成這項工作,但這種方法通常很繁瑣而且容易出錯,并且在需要跟蹤對象的層次結(jié)構(gòu)時,會變得越來越復(fù)雜。
可以想象一下編寫包含大量對象的大型業(yè)務(wù)應(yīng)用程序的情形,程序員不得不為每一個對象編寫代碼,以便將字段和屬性保存至磁盤以及從磁 盤還原這些字段和屬性。序列化提供了輕松實現(xiàn)這個目標(biāo)的快捷方法。公共語言運行時 (CLR) 管理對象在內(nèi)存中的分布,.NET 框架則通過使用反射提供自動的序列化機制。對象序列化后,類的名稱、程序集以及類實例的所有數(shù)據(jù)成員均被寫入存儲媒體中。對象通常用成員變量來存儲對其他實例的引用。類序列化后,序列化引擎將跟蹤所有已序列化的引用對象,以確保同一對象不被序列化多次。
.NET 框架所提供的序列化體系結(jié)構(gòu)可以自動正確處理對象圖表和循環(huán)引用。對對象圖表的唯一要求是,由正在進行序列化的對象所引用的所有對象都必須標(biāo)記為 Serializable(請參閱基 本序列化)。否則,當(dāng)序列化程序試圖序列化未標(biāo)記的對象時將會出現(xiàn)異常。當(dāng)反序列化已序列化的類時,將重新創(chuàng)建該類,并自動還原所有數(shù)據(jù)成員的值。
2.在網(wǎng)絡(luò)上傳送對象的字節(jié)序列
對象僅在創(chuàng)建對象的應(yīng)用程序域中有效。除非對象是從MarshalByRefObject派生得到或標(biāo)記為 Serializable,否則,任何將對象作為參數(shù)傳遞或?qū)⑵渥鳛榻Y(jié)果返回的嘗試都將失敗。
如果對象標(biāo)記為 Serializable,則該對象將被自動序列化,并從一個應(yīng)用程序域傳輸至另一個應(yīng)用程序域,然后進行反序列化,從而在第二個應(yīng)用程序域中產(chǎn)生出該對象的一個精確副本。此過程通常稱為按值封送。如果對象是從MarshalByRefObject派生得到,則從一個應(yīng)用程序域傳遞至另一個應(yīng)用程序域的是對象引用,而不是對象本身。也可以將從MarshalByRefObject派生得到的對象標(biāo)記為Serializable。
3.序列化和反序列化的主要作用有
- 在進程下次啟動時讀取上次保存的對象的信息
- 在不同的AppDomain或進程之間傳遞數(shù)據(jù)
- 在分布式應(yīng)用系統(tǒng)中傳遞數(shù)據(jù)
什么叫序列化?
我們都知道對象是暫時保存在內(nèi)存中的,不能用U盤考走了,有時為了使用介質(zhì)轉(zhuǎn)移對象,并且把對象的狀態(tài)保持下來,就需要把對象保存下來,這個過程就叫做序列化,通俗點,就是把人的魂(對象)收伏成一個魂器(可傳輸?shù)慕橘|(zhì))
什么叫反序列化?
就是再把介質(zhì)中的東西還原成對象,把魂器還原成人的過程。
在進行這些操作的時候都需要這個可以被序列化,要能被序列化,就得給類頭加[Serializable]特性。通常網(wǎng)絡(luò)程序為了傳輸安全才這么做。
序列化及反序列化
C#中用于對象和json相互轉(zhuǎn)換的原生類有兩個:
DataContractJsonSerializer
JavaScriptSerializer,
其中JavaScriptSerializer主要用于web的瀏覽器和服務(wù)器之間的通信。
這里主要講DataContractJsonSerializer的使用,要使用DataContractJsonSerializer,先要在項目中引用System.Runtime.Serialization。首先準(zhǔn)備一個測試的類Book:
二進制序列化
序列化為二進制
[Serializable]
1、Serializable特性的作用
序列化的attribute,是為了利用序列化的技術(shù) 準(zhǔn)備用于序列化的對象必須設(shè)置 [System.Serializable] 標(biāo)簽,該標(biāo)簽指示一個類可以序列化。 便于在網(wǎng)絡(luò)中傳輸和保存這個標(biāo)簽是類可以被序列化的特性,表示這個類可以被序列化。
[Serializable]
public class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
[Serializable]
public class Address
{
public string City { get; set; }
public string Road { get; set; }
}上述代碼中我們在類的頭部加入了 Serializable 特性,這代表著整個類對象都需要序列化,如果我們不需要序列化其中某個屬性的話只需在該屬性上加上 NonSerialized 特性即可。下面我們來看一下序列化和反序列化的代碼:
class Program
{
static void Main(string[] args)
{
#region 序列化
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
//二進制序列化
BinaryFormatter binFormat = new BinaryFormatter();
//返回保存的文檔
string fileName = Path.Combine(@"D:\", @"321.txt");
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
binFormat.Serialize(fStream, student);
}
#endregion
#region 反序列化
using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
{
fStream.Position = 0;
student = (Student)binFormat.Deserialize(fStream);
}
Console.WriteLine("Name: " + student.Name);
Console.WriteLine("Sex: " + student.Sex);
Console.WriteLine("Age: " + student.Age);
Console.WriteLine("Address: " + student.Address.City + " " + student.Address.Road);
#endregion
Console.ReadLine();
}
}
第二種寫法
using System;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
namespace ConsoleApp1
{
[Serializable] // 表示該類可以被序列化
class Person
{
private string name;
[NonSerialized] // 表示下面這個age字段不進行序列化
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public Person() { }
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public void SayHi()
{
Console.WriteLine("我是{0}, 今年{1}歲", name, age);
}
}
class Program
{
static void Main(string[] args)
{
string filePath = Path.Combine(@"D:\", @"321.txt");
// Use this for initialization
List<Person> listPers = new List<Person>();
Person per1 = new Person("張三", 18);
Person per2 = new Person("李四", 20);
listPers.Add(per1);
listPers.Add(per2);
SerializeMethod(listPers, filePath); // 序列化
DeserializeMethod(); // 反序列化
Console.WriteLine("Done ! ");
Console.ReadKey();
void DeserializeMethod() // 二進制反序列化
{
FileStream fs = new FileStream(filePath, FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
List<Person> list = bf.Deserialize(fs) as List<Person>;
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
list[i].SayHi();
}
}
fs.Close();
}
}
private static void SerializeMethod(List<Person> listPers, string filePath)
{
FileStream fs = new FileStream(filePath, FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, listPers);
fs.Close();
}
}
}寫法三
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace SerializableTest
{
class Program
{
static void Main(string[] args)
{
//創(chuàng)建一個格式化程序的實例
IFormatter formatter = new BinaryFormatter();
Console.WriteLine("對象序列化開始……");
var me = new Person
{
Sno = "200719",
Name = "yuananyun",
Sex="man",
Age=22
};
//創(chuàng)建一個文件流
Stream stream = new FileStream("c:/personInfo.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, me);
stream.Close();
Console.WriteLine("序列化結(jié)束!\n");
Console.WriteLine("反序列化開始……");
//反序列化
Stream destream = new FileStream("c:/personInfo.txt", FileMode.Open,
FileAccess.Read, FileShare.Read);
var stillme = (Person)formatter.Deserialize(destream);
stream.Close();
Console.WriteLine("反序列化結(jié)束,輸出對象信息……");
Console.WriteLine(stillme.DisplayInfo());
Console.ReadKey();
}
}
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SerializableTest
{
[Serializable]
public class Person
{
public string Sno { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public string DisplayInfo()
{
return "我的學(xué)號是:" +Sno+ "\n我的名字是:"+Name + "\n我的性別為:"+Sex+"\n我的年齡:"+Age+"\n";
}
}
}JSON
JSON 的英文全稱是 JavaScript Object Notation ,是一種輕量級的數(shù)據(jù)交換格式。完全獨立于語言的文本格式 易于人閱讀和編寫同時也易于機器解析和生成。JSON 是目前互聯(lián)網(wǎng)中主流的數(shù)據(jù)交換格式,同時也是很多開發(fā)語言配置文件的主流格式。
- 在 .NET 中存在兩個類對 JSON 進行處理,分別是 DataContractJsonSerializer 和 JavaScriptSerializer ,這兩個類的功能基本一致。 DataContractJsonSerializer 位于命名空間 System.Runtime.Serialization.Json 下,它的特點是必須使用 DataContract 以及 DataMember 屬性標(biāo)記成員。 JavaScriptSerializer 位于命名空間 System.Web.Script.Serialization 下,通過名字和它所在的命名空間我們可以得知它主要用在網(wǎng)絡(luò)通信中,它可以序列化任何類型的對象。同樣 .NET 中也存在一個強大的第三方 JSON 序列化/反序列化庫 Newtonsoft.Json ,他比前兩個類用起來要方便很多。下面我們對這三個序列化/反序列化的方式分別進行講解。
DataContractJsonSerializer
- 首先我們需要在項目中引用 DataContractJsonSerializer 所在的命名空間,這里要注意的時我們不僅要在項目中添加引用 System.Runtime.Serialization 還需要添加引用 System.ServiceModel.Web 。將這兩個命名空添加到命名空間后就可以在代碼中引入 DataContractJsonSerializer 的命名空間了。
Json支持下面兩種數(shù)據(jù)結(jié)構(gòu):
- 鍵值對的集合–各種不同的編程語言,都支持這種數(shù)據(jù)結(jié)構(gòu);
- 有序的列表類型值的集合–這其中包含數(shù)組,集合,矢量,或者序列,等等。
Json有下面幾種表現(xiàn)形式
1.對象
一個沒有順序的“鍵/值”,一個對象以花括號“{”開始,并以花括號"}"結(jié)束,在每一個“鍵”的后面,有一個冒號,并且使用逗號來分隔多個鍵值對。例如:
var user = {“name”:“Manas”,“gender”:“Male”,“birthday”:“1987-8-8”}
2.數(shù)組
設(shè)置值的順序,一個數(shù)組以中括號"[“開始,并以中括號”]"結(jié)束,并且所有的值使用逗號分隔,例如:
var userlist = [{“user”:{“name”:“Manas”,“gender”:“Male”,“birthday”:“1987-8-8”}},{“user”:{“name”:“Mohapatra”,“Male”:“Female”,“birthday”:“1987-7-7”}}]
3.字符串
任意數(shù)量的Unicode字符,使用引號做標(biāo)記,并使用反斜杠來分隔。例如:
- var userlist = “{“ID”:1,“Name”:“Manas”,“Address”:“India”}”
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace JsonSerializerAndDeSerializer
{
[DataContract]
public class Student
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Sex { get; set; }
}
}數(shù)據(jù)契約(DataContract) 服務(wù)契約定義了遠程訪問對象和可供調(diào)用的方法,數(shù)據(jù)契約則是服務(wù)端和客戶端之間要傳送的自定義數(shù)據(jù)類型。一旦聲明一個類型為DataContract,那么該類型就可以被序列化在服務(wù)端和客戶端之間傳送
只有聲明為DataContract的類型的對象可以被傳送,且只有成員屬性會被傳遞,成員方法不會被傳遞。默認(rèn)情況下類中的所有成員屬性都不會被序列化傳輸出去,如果需要將成員數(shù)據(jù)傳輸出去就需要在屬性頭部加入 DataMember
1.DataContractJsonSerializer
DataContractJsonSerializer類幫助我們序列化和反序列化Json,他在程序集 System.Runtime.Serialization.dll下的System.Runtime.Serialization.Json命名空間里。
Student stu = new Student()
{
ID = 1,
Name = "曹操",
Sex = "男",
Age = 1000
};
//序列化
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Student));
MemoryStream msObj = new MemoryStream();
//將序列化之后的Json格式數(shù)據(jù)寫入流中
js.WriteObject(msObj, stu);
msObj.Position = 0;
//從0這個位置開始讀取流中的數(shù)據(jù)
StreamReader sr = new StreamReader(msObj, Encoding.UTF8);
string json = sr.ReadToEnd();
sr.Close();
msObj.Close();
Console.WriteLine(json);
//反序列化
string toDes = json;
//string to = "{\"ID\":\"1\",\"Name\":\"曹操\",\"Sex\":\"男\(zhòng)",\"Age\":\"1230\"}";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(toDes)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(Student));
Student model = (Student)deseralizer.ReadObject(ms);// //反序列化ReadObject
Console.WriteLine("ID=" + model.ID);
Console.WriteLine("Name=" + model.Name);
Console.WriteLine("Age=" + model.Age);
Console.WriteLine("Sex=" + model.Sex);
}
Console.ReadKey();
Student stu = new Student()
{
ID = 1,
Name = "曹操",
Sex = "男",
Age = 1000
};
//序列化
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Student));
MemoryStream msObj = new MemoryStream();
//將序列化之后的Json格式數(shù)據(jù)寫入流中
js.WriteObject(msObj, stu);
msObj.Position = 0;
//從0這個位置開始讀取流中的數(shù)據(jù)
StreamReader sr = new StreamReader(msObj, Encoding.UTF8);
string json = sr.ReadToEnd();
sr.Close();
msObj.Close();
Console.WriteLine(json);
//反序列化
string toDes = json;
//string to = "{\"ID\":\"1\",\"Name\":\"曹操\",\"Sex\":\"男\(zhòng)",\"Age\":\"1230\"}";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(toDes)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(Student));
Student model = (Student)deseralizer.ReadObject(ms);// //反序列化ReadObject
Console.WriteLine("ID=" + model.ID);
Console.WriteLine("Name=" + model.Name);
Console.WriteLine("Age=" + model.Age);
Console.WriteLine("Sex=" + model.Sex);
}
Console.ReadKey();
Student stu = new Student()
{
ID = 1,
Name = "曹操",
Sex = "男",
Age = 1000
};
//序列化
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Student));
MemoryStream msObj = new MemoryStream();
//將序列化之后的Json格式數(shù)據(jù)寫入流中
js.WriteObject(msObj, stu);
msObj.Position = 0;
//從0這個位置開始讀取流中的數(shù)據(jù)
StreamReader sr = new StreamReader(msObj, Encoding.UTF8);
string json = sr.ReadToEnd();
sr.Close();
msObj.Close();
Console.WriteLine(json);
//反序列化
string toDes = json;
//string to = "{\"ID\":\"1\",\"Name\":\"曹操\",\"Sex\":\"男\(zhòng)",\"Age\":\"1230\"}";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(toDes)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(Student));
Student model = (Student)deseralizer.ReadObject(ms);// //反序列化ReadObject
Console.WriteLine("ID=" + model.ID);
Console.WriteLine("Name=" + model.Name);
Console.WriteLine("Age=" + model.Age);
Console.WriteLine("Sex=" + model.Sex);
}
Console.ReadKey();
2.JavaScriptJsonSerializer
Student stu = new Student()
{
ID = 1,
Name = "關(guān)羽",
Age = 2000,
Sex = "男"
};
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonData = js.Serialize(stu);//序列化
Console.WriteLine(jsonData);
////反序列化方式一:
string desJson = jsonData;
//Student model = js.Deserialize<Student>(desJson);// //反序列化
//string message = string.Format("ID={0},Name={1},Age={2},Sex={3}", model.ID, model.Name, model.Age, model.Sex);
//Console.WriteLine(message);
//Console.ReadKey();
////反序列化方式2
dynamic modelDy = js.Deserialize<dynamic>(desJson); //反序列化
string messageDy = string.Format("動態(tài)的反序列化,ID={0},Name={1},Age={2},Sex={3}",
modelDy["ID"], modelDy["Name"], modelDy["Age"], modelDy["Sex"]);//這里要使用索引取值,不能使用對象.屬性
Console.WriteLine(messageDy);
Console.ReadKey();
3.JSON.NET(性能最好)
List<Student> lstStuModel = new List<Student>()
{
new Student(){ID=1,Name="張飛",Age=250,Sex="男"},
new Student(){ID=2,Name="潘金蓮",Age=300,Sex="女"}
};
//Json.NET序列化
string jsonData = JsonConvert.SerializeObject(lstStuModel);
Console.WriteLine(jsonData);
Console.ReadKey();
//Json.NET反序列化
string json = @"{ 'Name':'C#','Age':'3000','ID':'1','Sex':'女'}";
Student descJsonStu = JsonConvert.DeserializeObject<Student>(json);//反序列化
Console.WriteLine(string.Format("反序列化: ID={0},Name={1},Sex={2},Sex={3}", descJsonStu.ID, descJsonStu.Name, descJsonStu.Age, descJsonStu.Sex));
Console.ReadKey();
XML

UTF-8
互聯(lián)網(wǎng)的普及,強烈要求出現(xiàn)一種統(tǒng)一的編碼方式。UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實現(xiàn)方式。其他實現(xiàn)方式還包括 UTF-16(字符用兩個字節(jié)或四個字節(jié)表示)和 UTF-32(字符用四個字節(jié)表示),不過在互聯(lián)網(wǎng)上基本不用。重復(fù)一遍,這里的關(guān)系是,UTF-8 是 Unicode 的實現(xiàn)方式之一。
UTF-8 最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節(jié)表示一個符號,根據(jù)不同的符號而變化字節(jié)長度。
UTF-8 的編碼規(guī)則很簡單,只有二條:
1)對于單字節(jié)的符號,字節(jié)的第一位設(shè)為0,后面7位為這個符號的 Unicode 碼。因此對于英語字母,UTF-8 編碼和 ASCII 碼是相同的。
2)對于n字節(jié)的符號(n > 1),第一個字節(jié)的前n位都設(shè)為1,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒有提及的二進制位,全部為這個符號的 Unicode 碼。
下表總結(jié)了編碼規(guī)則,字母x表示可用編碼的位。

XML和JSON比較
SON 和 XML 都用于接收 web 服務(wù)端的數(shù)據(jù)。
JSON 和 XML在寫法上有所不同,如下所示:
JSON 實例
{
"sites": [
{ "name":"菜鳥教程" , "url":"www.runoob.com" },
{ "name":"google" , "url":"www.google.com" },
{ "name":"微博" , "url":"www.weibo.com" }
]
}XML 實例
<sites>
<site>
<name>菜鳥教程</name> <url>www.runoob.com</url>
</site>
<site>
<name>google</name> <url>www.google.com</url>
</site>
<site>
<name>微博</name> <url>www.weibo.com</url>
</site>
</sites>JSON 與 XML 的相同之處:
- JSON 和 XML 數(shù)據(jù)都是 “自我描述” ,都易于理解。
- JSON 和 XML 數(shù)據(jù)都是有層次的結(jié)構(gòu)
- JSON 和 XML 數(shù)據(jù)可以被大多數(shù)編程語言使用
JSON 與 XML 的不同之處:
- JSON 不需要結(jié)束標(biāo)簽
- JSON 更加簡短
- JSON 讀寫速度更快
- JSON 可以使用數(shù)組
最大的不同是:XML 需要使用 XML 解析器來解析,JSON 可以使用標(biāo)準(zhǔn)的 JavaScript 函數(shù)來解析。
JSON.parse(): 將一個 JSON 字符串轉(zhuǎn)換為 JavaScript 對象。
JSON.stringify(): 于將 JavaScript 值轉(zhuǎn)換為 JSON 字符串。
為什么 JSON 比 XML 更好?
XML 比 JSON 更難解析。
JSON 可以直接使用現(xiàn)有的 JavaScript 對象解析。
針對 AJAX 應(yīng)用,JSON 比 XML 數(shù)據(jù)加載更快,而且更簡單:
使用 XML
- 獲取 XML 文檔
- 使用 XML DOM 迭代循環(huán)文檔
- 接數(shù)據(jù)解析出來復(fù)制給變量
使用 JSON
- 獲取 JSON 字符串
- JSON.Parse 解析 JSON 字符串
避坑指南
特性(Attribute)控制
通過給類成員打標(biāo)簽,可以精確控制序列化行為:
[JsonIgnore]:不參與序列化,常用于保護敏感數(shù)據(jù)或防止循環(huán)引用。[JsonPropertyName]:當(dāng) C# 命名規(guī)范(大駝峰)和 JSON 規(guī)范(小駝峰/下劃線)沖突時做映射。
性能陷阱
- 反射開銷:傳統(tǒng)的序列化器在運行時利用反射獲取類型信息,這很耗 CPU。
- Source Generation (源生成器):.NET 6+ 引入了
JsonSourceGenerationOptions。它在編譯時就生成好序列化代碼,不再依賴反射,極大提升了 AOT(原生編譯)環(huán)境和高性能場景的啟動速度。
循環(huán)引用問題
如果 A 引用 B,B 又引用 A,序列化器會陷入死循環(huán)報錯。
- 解法:在
JsonSerializerOptions中設(shè)置ReferenceHandler.Preserve。
到此這篇關(guān)于徹底掌握.NET中序列化反序列化問題及避坑指南的文章就介紹到這了,更多相關(guān).net序列化反序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ASP.NET?Core在WebApi項目中使用Cookie
這篇文章介紹了ASP.NET?Core在WebApi項目中使用Cookie的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03
ASP.NET2.0中用Gridview控件操作數(shù)據(jù)的代碼
在ASP.NET 2.0中,加入了許多新的功能和控件,相比asp.net 1.0/1.1,在各方面都有了很大的提高2012-10-10
ClickOnce DIY全自動更新下載升級的自我實現(xiàn)
ClickOnce DIY全自動更新下載升級的自我實現(xiàn)...2007-08-08
jQuery 插件autocomplete自動完成應(yīng)用(自動補全)(asp.net后臺)
項目中有時會用到自動補全查詢,就像Google搜索框、淘寶商品搜索功能,輸入漢字或字母,則以該漢字或字母開頭的相關(guān)條目會顯示出來供用戶選擇, autocomplete插件就是完成這樣的功能2011-10-10
顯示非站點目錄及映射網(wǎng)絡(luò)磁盤路徑的圖片
本文就將教你怎樣顯示非站點目錄下的圖片,你可以顯示站點所在服務(wù)器所有驅(qū)動器目錄的圖片,以及映射網(wǎng)絡(luò)磁盤路徑的圖片,感興趣的朋友可以了解下就當(dāng)鞏固知識了或許對你學(xué)習(xí).net有所幫助2013-02-02

