Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<PackageReference Include="BootstrapBlazor.Html2Pdf" Version="10.0.2" />
<PackageReference Include="BootstrapBlazor.IconPark" Version="10.0.0" />
<PackageReference Include="BootstrapBlazor.ImageCropper" Version="10.0.0" />
<PackageReference Include="BootstrapBlazor.IP2Region" Version="10.0.0" />
<PackageReference Include="BootstrapBlazor.IP2Region" Version="10.0.1" />
<PackageReference Include="BootstrapBlazor.JitsiMeet" Version="10.0.0" />
<PackageReference Include="BootstrapBlazor.JuHeIpLocatorProvider" Version="10.0.0" />
<PackageReference Include="BootstrapBlazor.Live2DDisplay" Version="10.0.0" />
Expand Down
6 changes: 4 additions & 2 deletions src/BootstrapBlazor.Server/Components/Samples/Locators.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/locator"
@page "/locator"

<h3>@Localizer["LocatorsTitle"]</h3>

Expand Down Expand Up @@ -38,14 +38,16 @@ Location = await provider.Locate(Ip);</Pre>
<p>@Localizer["LocatorsNormalIpTitle"]</p>
<p><code>112.224.74.239</code> @Localizer["LocatorsNormalTips3"]</p>
<p><code>183.160.236.53</code> @Localizer["LocatorsNormalTips4"]</p>
<p><code>240e:3b7:3272:d8d0:db09:c067:8d59:539e</code> @Localizer["LocatorsNormalTips5"]</p>

<DemoBlock Title="@Localizer["LocatorsNormalTitle"]" Introduction="@Localizer["LocatorsNormalIntro"]" Name="Normal">
<section ignore>
@((MarkupString)Localizer["LocatorsProviderDesc"].Value)
</section>
<div class="row g-3 form-inline">
<div class="col-12 col-sm-6">
<Select Items="_providers" Value="@ProviderName" OnValueChanged="OnProviderNameChanged" ShowLabel="true" DisplayText="LocatorProvider">
<Select Items="_providers" Value="@ProviderName" OnValueChanged="OnProviderNameChanged"
ShowLabel="true" DisplayText="LocatorProvider">
</Select>
</div>
<div class="col-12 col-sm-6">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
Expand Down Expand Up @@ -30,7 +30,7 @@ public partial class Locators

private string? Location { get; set; }

private string ProviderName { get; set; } = nameof(BaiduIpLocatorProviderV2);
private string ProviderName { get; set; } = nameof(BaiduIpLocatorProvider);

[NotNull]
private List<SelectedItem>? _providers = null;
Expand Down
3 changes: 2 additions & 1 deletion src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2982,9 +2982,10 @@
"LocatorsNormalTips2": "The <code>Startup</code> file add the following phrase to the <code>ConfigureServices</code> method",
"LocatorsNormalTips3": "Shandong, China Unicom",
"LocatorsNormalTips4": "Shushan District Hefei, Anhui China Telecom",
"LocatorsNormalTips5": "Bao'an District, Shenzhen, Guangdong China Telecom",
"LocatorsNormalTipsTitle": "Some geographic location query interfaces may return character sets from other character sets such as<code>gbk</code>, and the program may report an error",
"LocatorsNormalTitle": "Basic usage",
"LocatorsProviderDesc": "<p>The component library has two built-in free online geolocation locators, <code>BaiduIpLocatorProvider</code> <code>BaiduIpLocatorProviderV2</code><p><p>The component library has a built-in paid online geolocation locator <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget package</a> <a href=\"https://juhe.cn\" target=\"_blank\">Official website address</a></p><p>The component library has a built-in free offline geolocation locator <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget package</a></p>",
"LocatorsProviderDesc": "<p>The component library built-in free online geolocation locators, <code>BaiduIpLocatorProvider</code><p><p>The component library has a built-in paid online geolocation locator <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget package</a> <a href=\"https://juhe.cn\" target=\"_blank\">Official website address</a></p><p>The component library has a built-in free offline geolocation locator <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget package</a>. Supports IPv6 format.</p>",
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LocatorsProviderDesc text is now grammatically inconsistent: "built-in free online geolocation locators" is plural but only a single provider is listed, and the sentence is missing a verb/article (e.g., "has a built-in free online geolocation locator"). This string shows up in the sample docs UI, so it’s worth correcting for clarity.

Suggested change
"LocatorsProviderDesc": "<p>The component library built-in free online geolocation locators, <code>BaiduIpLocatorProvider</code><p><p>The component library has a built-in paid online geolocation locator <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget package</a> <a href=\"https://juhe.cn\" target=\"_blank\">Official website address</a></p><p>The component library has a built-in free offline geolocation locator <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget package</a>. Supports IPv6 format.</p>",
"LocatorsProviderDesc": "<p>The component library has a built-in free online geolocation locator, <code>BaiduIpLocatorProvider</code>.</p><p>The component library has a built-in paid online geolocation locator <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget package</a> <a href=\"https://juhe.cn\" target=\"_blank\">Official website address</a></p><p>The component library has a built-in free offline geolocation locator <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget package</a>. Supports IPv6 format.</p>",

Copilot uses AI. Check for mistakes.
"LocatorsSubTitle": "More for system log tracking and analysis",
"LocatorsTitle": "Get the IP geographic location"
},
Expand Down
3 changes: 2 additions & 1 deletion src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2982,9 +2982,10 @@
"LocatorsNormalTips2": "<code>Startup</code> 文件中 <code>ConfigureServices</code> 方法内增加下面这句话即可解决",
"LocatorsNormalTips3": "山东省 中国联通",
"LocatorsNormalTips4": "安徽省合肥市蜀山区 中国电信",
"LocatorsNormalTips5": "广东省深圳市宝安区 中国电信",
"LocatorsNormalTipsTitle": "某些地理位置查询接口返回字符集可能是其他字符集如 <code>gbk</code>,程序会报错;",
"LocatorsNormalTitle": "普通用法",
"LocatorsProviderDesc": "<p>组件库内置两个免费在线地理位置定位器分别为 <code>BaiduIpLocatorProvider</code> <code>BaiduIpLocatorProviderV2</code><p><p>组件库内置一个收费在线地理位置定位器 <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget 包</a> <a href=\"https://juhe.cn\" target=\"_blank\">官网地址</a></p><p>组件库内置一个免费离线地理位置定位器 <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget 包</a></p>",
"LocatorsProviderDesc": "<p>组件库内置免费一个在线地理位置定位器 <code>BaiduIpLocatorProvider</code><p><p>组件库内置一个收费在线地理位置定位器 <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget 包</a> <a href=\"https://juhe.cn\" target=\"_blank\">官网地址</a></p><p>组件库内置一个免费离线地理位置定位器 <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget 包</a> 支持 <code>IPv6<code> 格式</p>",
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LocatorsProviderDesc has malformed HTML: 支持 <code>IPv6<code> 格式 is missing the closing </code> for the IPv6 code span, which will break rendering/formatting in the docs page.

Suggested change
"LocatorsProviderDesc": "<p>组件库内置免费一个在线地理位置定位器 <code>BaiduIpLocatorProvider</code><p><p>组件库内置一个收费在线地理位置定位器 <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget 包</a> <a href=\"https://juhe.cn\" target=\"_blank\">官网地址</a></p><p>组件库内置一个免费离线地理位置定位器 <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget 包</a> 支持 <code>IPv6<code> 格式</p>",
"LocatorsProviderDesc": "<p>组件库内置免费一个在线地理位置定位器 <code>BaiduIpLocatorProvider</code><p><p>组件库内置一个收费在线地理位置定位器 <code>BootstrapBlazor.JuHeIpLocatorProvider</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.JuHeIpLocatorProvider\" target=\"_blank\">Nuget 包</a> <a href=\"https://juhe.cn\" target=\"_blank\">官网地址</a></p><p>组件库内置一个免费离线地理位置定位器 <code>BootstrapBlazor.IP2Region</code> <a href=\"https://www.nuget.org/packages/BootstrapBlazor.IP2Region\" target=\"_blank\">Nuget 包</a> 支持 <code>IPv6</code> 格式</p>",

Copilot uses AI. Check for mistakes.
"LocatorsSubTitle": "多用于系统日志跟踪与分析",
"LocatorsTitle": "获取 IP 地理位置"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,9 @@ public static IServiceCollection AddBootstrapBlazor(this IServiceCollection serv
// <para lang="en">IP Locator Service</para>
services.TryAddSingleton<IIpLocatorFactory, DefaultIpLocatorFactory>();
services.AddSingleton<IIpLocatorProvider, BaiduIpLocatorProvider>();
services.AddSingleton<IIpLocatorProvider, BaiduIpLocatorProviderV2>();

#if NET8_0_OR_GREATER
services.AddKeyedSingleton<IIpLocatorProvider, BaiduIpLocatorProvider>(nameof(BaiduIpLocatorProvider));
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes the built-in BaiduIpLocatorProviderV2 registration (and the PR also deletes the type), which is a breaking change for any consumers that reference nameof(BaiduIpLocatorProviderV2) or configure IpLocatorOptions.ProviderName to BaiduIpLocatorProviderV2. Today DefaultIpLocatorFactory.Create indexes _providers[providerKey] and will throw KeyNotFoundException for an unknown key, so upgrades can fail at runtime. If the intent is to deprecate V2, consider keeping a compatibility shim (e.g., keep the type and mark [Obsolete], or map the old key to BaiduIpLocatorProvider / provide a safe fallback) and update all docs/samples that still mention V2 (e.g., ConnectionServices.razor, IpLocatorOptions XML docs).

Suggested change
services.AddKeyedSingleton<IIpLocatorProvider, BaiduIpLocatorProvider>(nameof(BaiduIpLocatorProvider));
services.AddKeyedSingleton<IIpLocatorProvider, BaiduIpLocatorProvider>(nameof(BaiduIpLocatorProvider));
// Compatibility shim: map legacy BaiduIpLocatorProviderV2 key to current provider
services.AddKeyedSingleton<IIpLocatorProvider, BaiduIpLocatorProvider>("BaiduIpLocatorProviderV2");

Copilot uses AI. Check for mistakes.
services.AddKeyedSingleton<IIpLocatorProvider, BaiduIpLocatorProviderV2>(nameof(BaiduIpLocatorProviderV2));
#endif

// <para lang="zh">节日服务</para>
Expand Down
169 changes: 0 additions & 169 deletions src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProviderV2.cs

This file was deleted.

50 changes: 3 additions & 47 deletions test/UnitTest/Services/IpLocatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,40 +36,19 @@ public async Task BaiduIpLocatorProvider_Ok()
// 关闭缓存
option.Value.IpLocatorOptions.EnableCache = false;
option.Value.IpLocatorOptions.SlidingExpiration = TimeSpan.FromMinutes(5);
option.Value.IpLocatorOptions.ProviderName = nameof(BaiduIpLocatorProviderV2);
option.Value.IpLocatorOptions.ProviderName = nameof(BaiduIpLocatorProvider);
await provider.Locate("223.91.188.112");
Assert.Equal("美国", result);
}

[Fact]
public async Task BaiduIpLocatorProviderV2_Ok()
{
var factory = Context.Services.GetRequiredService<IHttpClientFactory>();
var option = Context.Services.GetRequiredService<IOptions<BootstrapBlazorOptions>>();
var logger = Context.Services.GetRequiredService<ILogger<MockProviderV2>>();
var provider = new MockProviderV2(factory, option, logger);

var result = await provider.Locate("127.0.0.1");
Assert.Equal("localhost", result);

result = await provider.Locate("");
Assert.Equal("localhost", result);

// 河南省漯河市 移动
result = await provider.Locate("223.91.188.112");
Assert.Equal("省份城市区县 测试", result);
}

[Fact]
public void Factory_Ok()
{
var factory = Context.Services.GetRequiredService<IIpLocatorFactory>();
Assert.NotNull(factory.Create("BaiduIpLocatorProviderV2"));
Assert.NotNull(factory.Create("BaiduIpLocatorProvider"));
Assert.NotNull(factory.Create());

Assert.NotNull(Context.Services.GetKeyedService<IIpLocatorProvider>("BaiduIpLocatorProvider"));
Assert.NotNull(Context.Services.GetKeyedService<IIpLocatorProvider>("BaiduIpLocatorProviderV2"));
}

[Fact]
Expand All @@ -89,8 +68,8 @@ public async Task Fetch_Error()
var result = await provider.Locate("223.91.188.112");
Assert.Null(result);

var cancelPprovider = new MockProviderFetchCancelError(factory, option, logger);
result = await cancelPprovider.Locate("223.91.188.112");
var cancelProvider = new MockProviderFetchCancelError(factory, option, logger);
result = await cancelProvider.Locate("223.91.188.112");
Assert.Null(result);
}

Expand All @@ -104,11 +83,6 @@ public async Task Fetch_Result_Fail()
var provider = new MockBaiduProvider(factory, option, logger);
var result = await provider.Locate("223.91.188.112");
Assert.Null(result);

var loggerV2 = Context.Services.GetRequiredService<ILogger<MockBaiduProviderV2>>();
var providerV2 = new MockBaiduProviderV2(factory, option, loggerV2);
result = await providerV2.Locate("223.91.188.112");
Assert.Null(result);
}

class MockProviderFetchError(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockProviderFetchError> logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
Expand All @@ -130,15 +104,6 @@ class MockBaiduProvider(IHttpClientFactory httpClientFactory, IOptions<Bootstrap
}
}

class MockBaiduProviderV2(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockBaiduProviderV2> logger) : BaiduIpLocatorProviderV2(httpClientFactory, option, logger)
{
protected override Task<string?> Fetch(string url, HttpClient client, CancellationToken token)
{
client = new HttpClient(new MockHttpNullMessageHandler(), true);
return base.Fetch(url, client, token);
}
}

class MockProvider(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockProvider> logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
{
protected override Task<string?> Fetch(string url, HttpClient client, CancellationToken token)
Expand All @@ -148,15 +113,6 @@ class MockProvider(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazo
}
}

class MockProviderV2(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockProviderV2> logger) : BaiduIpLocatorProviderV2(httpClientFactory, option, logger)
{
protected override Task<string?> Fetch(string url, HttpClient client, CancellationToken token)
{
client = new HttpClient(new MockHttpSuccessMessageHandlerV2(), true);
return base.Fetch(url, client, token);
}
}

class MockHttpNullMessageHandler : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Expand Down
Loading