diff --git a/src/BootstrapBlazor.Server/Components/Pages/Localization.razor b/src/BootstrapBlazor.Server/Components/Pages/Localization.razor index 8edd6543d88..f8585c351f7 100644 --- a/src/BootstrapBlazor.Server/Components/Pages/Localization.razor +++ b/src/BootstrapBlazor.Server/Components/Pages/Localization.razor @@ -72,8 +72,6 @@

2. @Localizer["N24"]

- -
builder.Services.AddRazorPages();
 builder.Services.AddServerSideBlazor();
 
@@ -97,33 +95,6 @@ if (option != null)
     app.UseRequestLocalization(option.Value);
 }
 
-
- -
public class Startup
-{
-    public void ConfigureServices(IServiceCollection services)
-    {
-        // @Localizer["N28"]
-        services.AddBootstrapBlazor();
-
-        // @Localizer["N29"]
-        services.AddRequestLocalization<IOptions<BootstrapBlazorOptions>>((localizerOption, blazorOption) =>
-        {
-            var supportedCultures = blazorOption.Value.GetSupportedCultures();
-
-            localizerOption.SupportedCultures = supportedCultures;
-            localizerOption.SupportedUICultures = supportedCultures;
-        });
-    }
-
-    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
-    {
-        // @Localizer["N30"]
-        app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>()!.Value);
-    }
-}
-
-

3. @Localizer["N31"]

[Route("[controller]/[action]")]
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Locators.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Locators.razor.cs
index a94a2673bb5..147d5b41468 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Locators.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/Locators.razor.cs
@@ -71,6 +71,11 @@ private async Task OnClick()
         {
             var provider = IpLocatorFactory.Create(ProviderName);
             Location = await provider.Locate(Ip);
+
+            if (!string.IsNullOrEmpty(provider.LastError))
+            {
+                Location = provider.LastError;
+            }
         }
     }
 
diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json
index 92dd7cb9b9e..f3fec3b3a30 100644
--- a/src/BootstrapBlazor.Server/Locales/en-US.json
+++ b/src/BootstrapBlazor.Server/Locales/en-US.json
@@ -621,10 +621,7 @@
     "N25": "Add Bootstrap Blazor components",
     "N26": "Add multi-language support configuration information",
     "N27": "Enable localization",
-    "N28": "Add BootstrapBlazor component",
-    "N29": "Add localization service configuration information",
     "N3": "Type key-value information as a resource file, which is parsed as",
-    "N30": "Enable localization middleware and set supported culture info",
     "N31": "Implement UI localization information storage (for example, cookies)",
     "N32": "Add UI that allows users to change localization",
     "N33": "Please select language",
diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json
index 97bcf912e25..16f47be90d2 100644
--- a/src/BootstrapBlazor.Server/Locales/zh-CN.json
+++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json
@@ -621,10 +621,7 @@
     "N25": "增加 Bootstrap Blazor 组件",
     "N26": "增加多语言支持配置信息",
     "N27": "启用本地化",
-    "N28": "增加 BootstrapBlazor 组件",
-    "N29": "增加本地化服务配置信息",
     "N3": "类型的键值信息作为资源文件,将其解析为",
-    "N30": "启用本地化中间件并设置支持的文化信息",
     "N31": "实现 UI 本地化信息存储(例如,cookie)",
     "N32": "添加允许用户更改本地化的 UI",
     "N33": "请选择语言",
diff --git a/src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProvider.cs b/src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProvider.cs
index a42c5db5080..d6e8c8f8acf 100644
--- a/src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProvider.cs
+++ b/src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProvider.cs
@@ -60,8 +60,25 @@ public class BaiduIpLocatorProvider(IHttpClientFactory httpClientFactory, IOptio
     /// 
     protected virtual async Task Fetch(string url, HttpClient client, CancellationToken token)
     {
-        var result = await client.GetFromJsonAsync(url, token);
-        return result?.ToString();
+        string? ret = null;
+        try
+        {
+            var result = await client.GetFromJsonAsync(url, token);
+            if (result is { Status: "0" })
+            {
+                var location = result.Data.FirstOrDefault();
+                if (location != null)
+                {
+                    ret = location.Location;
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            LastError = ex.Message;
+        }
+
+        return ret;
     }
 
     /// 
@@ -81,22 +98,7 @@ class LocationResult
         /// 获得/设置 定位信息
         /// Gets or sets Location Info
         /// 
-        public List? Data { get; set; }
-
-        /// 
-        /// 
-        /// 
-        /// 
-        /// 
-        public override string? ToString()
-        {
-            string? ret = null;
-            if (Status == "0")
-            {
-                ret = Data?.FirstOrDefault()?.Location;
-            }
-            return ret;
-        }
+        public List Data { get; set; } = [];
     }
 
     [ExcludeFromCodeCoverage]
diff --git a/src/BootstrapBlazor/Services/IPLocator/DefaultIPLocatorProvider.cs b/src/BootstrapBlazor/Services/IPLocator/DefaultIPLocatorProvider.cs
index af678cee8c5..1b378415aa7 100644
--- a/src/BootstrapBlazor/Services/IPLocator/DefaultIPLocatorProvider.cs
+++ b/src/BootstrapBlazor/Services/IPLocator/DefaultIPLocatorProvider.cs
@@ -42,10 +42,15 @@ protected DefaultIpLocatorProvider(IOptions options)
     private readonly List _localhostList = [.. new[] { "::1", "127.0.0.1" }];
 
     /// 
-    /// 
+    /// 
     /// 
     public string? Key { get; set; }
 
+    /// 
+    /// 
+    /// 
+    public string? LastError { get; protected set; }
+
     /// 
     /// 
     /// 
@@ -53,6 +58,7 @@ protected DefaultIpLocatorProvider(IOptions options)
     public async Task Locate(string? ip)
     {
         string? ret = null;
+        LastError = null;
 
         // 解析本机地址
         if (string.IsNullOrEmpty(ip) || _localhostList.Any(p => p == ip))
diff --git a/src/BootstrapBlazor/Services/IPLocator/IIpLocatorProvider.cs b/src/BootstrapBlazor/Services/IPLocator/IIpLocatorProvider.cs
index afd5d20d048..e576b7b895e 100644
--- a/src/BootstrapBlazor/Services/IPLocator/IIpLocatorProvider.cs
+++ b/src/BootstrapBlazor/Services/IPLocator/IIpLocatorProvider.cs
@@ -23,4 +23,10 @@ public interface IIpLocatorProvider
     /// 
     /// 
     Task Locate(string? ip);
+
+    /// 
+    /// 获得 上次错误描述信息
+    /// Get the previous error detail
+    /// 
+    string? LastError { get; }
 }
diff --git a/test/UnitTest/Services/IpLocatorTest.cs b/test/UnitTest/Services/IpLocatorTest.cs
index 767da1b5b70..7a1a3748108 100644
--- a/test/UnitTest/Services/IpLocatorTest.cs
+++ b/test/UnitTest/Services/IpLocatorTest.cs
@@ -39,6 +39,7 @@ public async Task BaiduIpLocatorProvider_Ok()
         option.Value.IpLocatorOptions.ProviderName = nameof(BaiduIpLocatorProvider);
         await provider.Locate("223.91.188.112");
         Assert.Equal("美国", result);
+        Assert.Null(provider.LastError);
     }
 
     [Fact]
@@ -85,6 +86,19 @@ public async Task Fetch_Result_Fail()
         Assert.Null(result);
     }
 
+    [Fact]
+    public async Task Fetch_Exception()
+    {
+        var factory = Context.Services.GetRequiredService();
+        var option = Context.Services.GetRequiredService>();
+        option.Value.IpLocatorOptions.EnableCache = false;
+        var logger = Context.Services.GetRequiredService>();
+        var provider = new MockErrorProvider(factory, option, logger);
+        var result = await provider.Locate("223.91.188.112");
+        Assert.Null(result);
+        Assert.NotNull(provider.LastError);
+    }
+
     class MockProviderFetchError(IHttpClientFactory httpClientFactory, IOptions option, ILogger logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
     {
         protected override Task Fetch(string url, HttpClient client, CancellationToken token) => throw new InvalidOperationException();
@@ -113,57 +127,41 @@ class MockProvider(IHttpClientFactory httpClientFactory, IOptions option, ILogger logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
     {
-        protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
-        {
-            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
-            {
-                Content = new StringContent("null")
-            });
-        }
-    }
-
-    class MockHttpSuccessMessageHandler : HttpMessageHandler
-    {
-        protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+        protected override Task Fetch(string url, HttpClient client, CancellationToken token)
         {
-            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
-            {
-                Content = new StringContent("{\"status\":\"0\",\"t\":\"\",\"set_cache_time\":\"\",\"data\":[{\"ExtendedLocation\":\"\",\"OriginQuery\":\"20.205.243.166\",\"appinfo\":\"\",\"disp_type\":0,\"fetchkey\":\"20.205.243.166\",\"location\":\"美国\",\"origip\":\"20.205.243.166\",\"origipquery\":\"20.205.243.166\",\"resourceid\":\"6006\",\"role_id\":0,\"shareImage\":1,\"showLikeShare\":1,\"showlamp\":\"1\",\"titlecont\":\"IP地址查询\",\"tplt\":\"ip\"}]}")
-            });
+            client = new HttpClient(new MockHttpExceptionMessageHandler(), true);
+            return base.Fetch(url, client, token);
         }
     }
 
-    class MockHttpSuccessMessageHandlerV2 : HttpMessageHandler
+    class MockHttpExceptionMessageHandler : HttpMessageHandler
     {
         protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         {
-            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
-            {
-                Content = new StringContent("{\"code\":\"Success\",\"data\": {\"country\": \"中国\", \"prov\":\"省份\", \"city\":\"城市\", \"district\":\"区县\", \"isp\": \"测试\"}}")
-            });
+            throw new Exception("error test");
         }
     }
 
-    class MockHttpSuccessMessageHandlerJuHe : HttpMessageHandler
+    class MockHttpNullMessageHandler : HttpMessageHandler
     {
         protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         {
             return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
             {
-                Content = new StringContent("{\"reason\": \"查询成功\", \"error_code\": 0, \"result\": {\"country\": \"中国\", \"prov\":\"省份\", \"city\":\"城市\", \"district\":\"区县\", \"isp\": \"测试\"}}")
+                Content = new StringContent("null")
             });
         }
     }
 
-    class MockHttpFailedMessageHandlerJuHe : HttpMessageHandler
+    class MockHttpSuccessMessageHandler : HttpMessageHandler
     {
         protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         {
             return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
             {
-                Content = new StringContent("{\"reason\": \"错误的请求KEY\", \"error_code\": 10001, \"result\": null}")
+                Content = new StringContent("{\"status\":\"0\",\"t\":\"\",\"set_cache_time\":\"\",\"data\":[{\"ExtendedLocation\":\"\",\"OriginQuery\":\"20.205.243.166\",\"appinfo\":\"\",\"disp_type\":0,\"fetchkey\":\"20.205.243.166\",\"location\":\"美国\",\"origip\":\"20.205.243.166\",\"origipquery\":\"20.205.243.166\",\"resourceid\":\"6006\",\"role_id\":0,\"shareImage\":1,\"showLikeShare\":1,\"showlamp\":\"1\",\"titlecont\":\"IP地址查询\",\"tplt\":\"ip\"}]}")
             });
         }
     }