CountryListBox ASP.NET Web 控件,列出国家并自动检测访问者的国家。






4.55/5 (20投票s)
2002年12月2日
6分钟阅读

256479

5029
一个派生自 DropDownList 的控件,该控件列出所有国家,并执行 IP 地址数据库查找,以自动确定访问者的国家。
引言
本文的目的是展示如何创建一个更专业的 DropDownList
Web 控件 - 特别是用于显示国家的控件 - 适用于 ASP.NET Web Forms。其主要优点是(不仅显示所有国家,手动添加每个国家到 HTML 会非常繁琐),而且它还可以自动识别访问者来自哪个国家,或者说,访问者正在访问网站的哪个国家。
该 Web 控件使用来自 MaxMind 的数据库,特别是其 GeoIP Free Database。MaxMind 还提供了一个 C# 类来访问其数据库。
这是一个非常简单的控件,大部分工作由现成的 CountryLookup
类完成,因此最好的方法是概述它的工作原理,然后介绍实现细节。
一如既往,我的网站上提供了一个 实时演示。
工作原理
总的来说,CountryListBox
Web 控件派生自 DropDownList
,并将一个 ASCII 文本文件的内容添加到 CountryListBox
的 Items
集合中(国家列表)。MaxMind 提供了一个 CountryLookup
类,该类包含一个每个国家的字符串数组 - 创建了一个实用程序来将这个数组的内容转储到一个 ASCII 文本文件中。数组的一部分包含“N/A”和“Anonymous Proxy”,这些内容已从文本文件中移除。这个文本文件包含在两个存档中,所以您不必担心重新创建它。
在加载完国家列表后,会根据 IP 数据库进行查找以确定当前访问者的位置,然后将其选中在下拉列表中 - 允许用户在错误时进行更正。除此之外,它的行为与任何其他 DropDownList
控件一样。
现在是 MaxMind GeoIP 数据库背后的技术细节(理解这些并非绝对必要,因为 C# 类是由 MaxMind 提供的)。
MaxMind 存储 IP 地址范围,每个记录也都会标记一个国家。例如(CSV 格式),"1029177344","1029439487","AU","Australia"
。IP 地址计算方法是 ipnum = 16777216*w + 65536*x + 256*y + z
。例如,根据 24.24.24.24 计算 IP 号码:404232216 = 16777216*24 + 65536*24 + 256*24 + 24
。所有这些都由 CountryLookup
类处理 - 该类可直接从 MaxMind 下载(但已包含在 CountryListBox
程序集中)。
实现细节
该控件的设计相对简单,大部分工作是在 OnInit
重写方法中完成的。其目的是将所有国家添加到控件的 Items 集合中,然后选择访问者所在的国家。
OnInit
下面是 OnInit
方法的部分代码。它包括确定是否应使用应用程序缓存来存储 Geo IP 数据库的代码(通过 CountryListBox
的 CacheDatabase
属性设置)。如果使用缓存,并且检测到数据尚未存储,它会将文件加载到一个 MemoryStream
对象中(这是通过 FileToMemory
静态方法实现的 - 我将其添加到 CountryLookup
类中)。然后,这个 MemoryStream
对象会被存储在应用程序缓存中。
// Check to see if the application cache should be used
if (useAppCache)
{
// Check to see whether the IP Database is
// already in the Application Cache
if (Context.Cache.Get("GeoIPData") == null)
// No, so store it as well as setting a dependency on the file
Context.Cache.Insert("GeoIPData",
CountryLookup.FileToMemory(
ConfigurationSettings.AppSettings["GeoDatFile"]),
new CacheDependency
(ConfigurationSettings.AppSettings["GeoDatFile"]));
然后调用 LoadCountries
方法来填充 Items
集合,并进行查找,然后选择匹配的国家。
// Load the countries from the ASCII file into the control
LoadCountries();
// Perform the lookup using the MemoryStream taken from the Cache
CountryLookup cl = new CountryLookup(
((MemoryStream)Context.Cache.Get("GeoIPData"))
);
// What country is the visitor from?
string visitorCountry = cl.lookupCountryName(
this.Page.Request.ServerVariables["REMOTE_ADDR"]
);
// Select the country in the control
this.SelectedIndex = this.Items.IndexOf(
new ListItem(visitorCountry,visitorCountry)
);
}
CountryLookup 更改
CountryLookup
类由 MaxMind 提供,因此需要进行一些更改才能在存储在内存中的数据库上执行搜索。由于 .NET 的流基础设施,这变得相当容易。
部署演示
演示中包含一个测试 Web 窗体、GeoIP 数据库、国家文本文件和 CountryListBox
程序集。目录结构已准备好复制,但需要更改 *web.config* 中的内容以反映不同的路径。您可以将这些文件放在任何地方(例如,公共可访问文件结构之外),只需确保 ASP.NET 用户帐户具有必要的访问权限。
您需要做一些基本的事情才能将控件添加到您的页面:
- 在页面顶部添加导入语句
<%@ Register TagPrefix="etier" Namespace="Etier" Assembly="CountryListBox" %>
- 然后在页面中添加该标签,它应该支持任何标准的
DropDownList
属性(尽管我没有对此进行彻底测试 :))<etier:CountryListBox Id="MyListBox" RunAt="server" CacheDatabase=true CacheCountries=true />
性能
我对控件进行了有限的测试,以了解它在负载下的性能。我使用 Windows XP Professional 作为开发平台,该平台具有受限制的 IIS 版本 - 限制为 10 个并发连接。我使用 Microsoft Application Center Test 进行测试,测试涉及在 5 分钟内尽可能多地加载演示页面。
非缓存版本结果
下方的图表显示了使用标准控件(无缓存)的测试结果。每次请求页面时,都会加载并搜索 GeoIP 数据库文件,并且还会从文本文件中加载国家。图表下方是一些测试期间记录的基本统计数据。
Average requests per second: 32.47
Average time to first byte (msecs): 279.39
Average time to last byte (msecs): 279.55
Response Code: 403 - The server understood the request, but is refusing
to fulfill it.
Count: 5,429
Percent (%): 55.73
Response Code: 200 - The request completed successfully.
Count: 4,313
Percent (%): 44.27
由于我的本地机器并不是真正设计用来作为服务器(它是一台基于 Athlon XP 2000+ 的机器,拥有 512MB RAM,但没有 SCSI 硬盘),因此可以公平地假设专用服务器的性能会更好。尽管如此,该服务器每秒只能处理平均 32 个请求。
缓存结果
为了提高性能,我使用了 ASP.NET 的应用程序缓存来存储 GeoIP 数据库和国家列表。可以通过 CacheDatabase
和 CacheCountries
属性来设置使用这两者的选项。然后我运行了相同的测试脚本,下面的结果图表显示了显着的差异(远远超出我的预期)。同样,下方包含一些基本统计数据。
Average requests per second: 146.01
Average time to first byte (msecs): 43.48
Average time to last byte (msecs): 43.76
Response Code: 403 - The server understood the request, but is refusing
to fulfill it.
Count: 6
Percent (%): 0.01
Response Code: 200 - The request completed successfully.
Count: 43,797
Percent (%): 99.99
由于缓存,每秒可处理的请求数量已从 32 个增加到 146 个,增长了约 350%。
结论
感谢 Per Soderlind 撰写了一篇文章,该文章首先告诉我 MaxMind 的 GeoIP 数据库。也感谢 MaxMind 免费提供数据库。似乎它对商业应用程序也是免费的 -- 但也提供商业服务,包括区域、州甚至 NetBlock 所有者的详细信息!
这是一个非常简单的控件,但它也非常有用!它应该可以防止这么多人错误地填写表格。再次,如果您有任何意见或问题,请随时通过电子邮件与我联系,或者在下方发布消息。