Skip to content

Commit 27a4c03

Browse files
authored
feat(IIpLocatorProvider): add LastError property (#7708)
* doc(Localization): remove NET5/6 tab item * doc: 更新注释文档 * feat: 增加 LastError 参数 * refactor: 重构代码 * doc: 更新示例 * doc: 删除空行 * test: 提高代码覆盖率 * test: 增加单元测试
1 parent 9cfd4ff commit 27a4c03

8 files changed

Lines changed: 62 additions & 80 deletions

File tree

src/BootstrapBlazor.Server/Components/Pages/Localization.razor

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@
7272

7373
<p><b>2. @Localizer["N24"]</b></p>
7474

75-
<Tab>
76-
<TabItem Text="NET6.0" Icon="fa-solid fa-code" Closable="false">
7775
<Pre>builder.Services.AddRazorPages();
7876
builder.Services.AddServerSideBlazor();
7977

@@ -97,33 +95,6 @@ if (option != null)
9795
app.UseRequestLocalization(option.Value);
9896
}
9997
</Pre>
100-
</TabItem>
101-
<TabItem Text="NET5.0" Icon="fa-solid fa-code" Closable="false">
102-
<Pre class="mb-3">public class Startup
103-
{
104-
public void ConfigureServices(IServiceCollection services)
105-
{
106-
// @Localizer["N28"]
107-
services.AddBootstrapBlazor();
108-
109-
// @Localizer["N29"]
110-
services.AddRequestLocalization&lt;IOptions&lt;BootstrapBlazorOptions&gt;&gt;((localizerOption, blazorOption) =>
111-
{
112-
var supportedCultures = blazorOption.Value.GetSupportedCultures();
113-
114-
localizerOption.SupportedCultures = supportedCultures;
115-
localizerOption.SupportedUICultures = supportedCultures;
116-
});
117-
}
118-
119-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
120-
{
121-
// @Localizer["N30"]
122-
app.UseRequestLocalization(app.ApplicationServices.GetService&lt;IOptions&lt;RequestLocalizationOptions&gt;&gt;()!.Value);
123-
}
124-
}</Pre>
125-
</TabItem>
126-
</Tab>
12798

12899
<p><b>3. @Localizer["N31"]</b></p>
129100
<Pre class="mb-3">[Route("[controller]/[action]")]

src/BootstrapBlazor.Server/Components/Samples/Locators.razor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ private async Task OnClick()
7171
{
7272
var provider = IpLocatorFactory.Create(ProviderName);
7373
Location = await provider.Locate(Ip);
74+
75+
if (!string.IsNullOrEmpty(provider.LastError))
76+
{
77+
Location = provider.LastError;
78+
}
7479
}
7580
}
7681

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,7 @@
621621
"N25": "Add Bootstrap Blazor components",
622622
"N26": "Add multi-language support configuration information",
623623
"N27": "Enable localization",
624-
"N28": "Add BootstrapBlazor component",
625-
"N29": "Add localization service configuration information",
626624
"N3": "Type key-value information as a resource file, which is parsed as",
627-
"N30": "Enable localization middleware and set supported culture info",
628625
"N31": "Implement UI localization information storage (for example, cookies)",
629626
"N32": "Add UI that allows users to change localization",
630627
"N33": "Please select language",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,7 @@
621621
"N25": "增加 Bootstrap Blazor 组件",
622622
"N26": "增加多语言支持配置信息",
623623
"N27": "启用本地化",
624-
"N28": "增加 BootstrapBlazor 组件",
625-
"N29": "增加本地化服务配置信息",
626624
"N3": "类型的键值信息作为资源文件,将其解析为",
627-
"N30": "启用本地化中间件并设置支持的文化信息",
628625
"N31": "实现 UI 本地化信息存储(例如,cookie)",
629626
"N32": "添加允许用户更改本地化的 UI",
630627
"N33": "请选择语言",

src/BootstrapBlazor/Services/IPLocator/BaiduIpLocatorProvider.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,25 @@ public class BaiduIpLocatorProvider(IHttpClientFactory httpClientFactory, IOptio
6060
/// <param name="token"></param>
6161
protected virtual async Task<string?> Fetch(string url, HttpClient client, CancellationToken token)
6262
{
63-
var result = await client.GetFromJsonAsync<LocationResult>(url, token);
64-
return result?.ToString();
63+
string? ret = null;
64+
try
65+
{
66+
var result = await client.GetFromJsonAsync<LocationResult>(url, token);
67+
if (result is { Status: "0" })
68+
{
69+
var location = result.Data.FirstOrDefault();
70+
if (location != null)
71+
{
72+
ret = location.Location;
73+
}
74+
}
75+
}
76+
catch (Exception ex)
77+
{
78+
LastError = ex.Message;
79+
}
80+
81+
return ret;
6582
}
6683

6784
/// <summary>
@@ -81,22 +98,7 @@ class LocationResult
8198
/// <para lang="zh">获得/设置 定位信息</para>
8299
/// <para lang="en">Gets or sets Location Info</para>
83100
/// </summary>
84-
public List<LocationData>? Data { get; set; }
85-
86-
/// <summary>
87-
/// <inheritdoc/>
88-
/// <para lang="en"><inheritdoc/></para>
89-
/// </summary>
90-
/// <returns></returns>
91-
public override string? ToString()
92-
{
93-
string? ret = null;
94-
if (Status == "0")
95-
{
96-
ret = Data?.FirstOrDefault()?.Location;
97-
}
98-
return ret;
99-
}
101+
public List<LocationData> Data { get; set; } = [];
100102
}
101103

102104
[ExcludeFromCodeCoverage]

src/BootstrapBlazor/Services/IPLocator/DefaultIPLocatorProvider.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,23 @@ protected DefaultIpLocatorProvider(IOptions<BootstrapBlazorOptions> options)
4242
private readonly List<string> _localhostList = [.. new[] { "::1", "127.0.0.1" }];
4343

4444
/// <summary>
45-
/// <inheritdoc/>
45+
/// <inheritdoc cref="IIpLocatorProvider.Key"/>
4646
/// </summary>
4747
public string? Key { get; set; }
4848

49+
/// <summary>
50+
/// <inheritdoc cref="IIpLocatorProvider.LastError"/>
51+
/// </summary>
52+
public string? LastError { get; protected set; }
53+
4954
/// <summary>
5055
/// <inheritdoc/>
5156
/// </summary>
5257
/// <param name="ip"></param>
5358
public async Task<string?> Locate(string? ip)
5459
{
5560
string? ret = null;
61+
LastError = null;
5662

5763
// 解析本机地址
5864
if (string.IsNullOrEmpty(ip) || _localhostList.Any(p => p == ip))

src/BootstrapBlazor/Services/IPLocator/IIpLocatorProvider.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ public interface IIpLocatorProvider
2323
/// </summary>
2424
/// <param name="ip"></param>
2525
Task<string?> Locate(string? ip);
26+
27+
/// <summary>
28+
/// <para lang="zh">获得 上次错误描述信息</para>
29+
/// <para lang="en">Get the previous error detail</para>
30+
/// </summary>
31+
string? LastError { get; }
2632
}

test/UnitTest/Services/IpLocatorTest.cs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public async Task BaiduIpLocatorProvider_Ok()
3939
option.Value.IpLocatorOptions.ProviderName = nameof(BaiduIpLocatorProvider);
4040
await provider.Locate("223.91.188.112");
4141
Assert.Equal("美国", result);
42+
Assert.Null(provider.LastError);
4243
}
4344

4445
[Fact]
@@ -85,6 +86,19 @@ public async Task Fetch_Result_Fail()
8586
Assert.Null(result);
8687
}
8788

89+
[Fact]
90+
public async Task Fetch_Exception()
91+
{
92+
var factory = Context.Services.GetRequiredService<IHttpClientFactory>();
93+
var option = Context.Services.GetRequiredService<IOptions<BootstrapBlazorOptions>>();
94+
option.Value.IpLocatorOptions.EnableCache = false;
95+
var logger = Context.Services.GetRequiredService<ILogger<MockErrorProvider>>();
96+
var provider = new MockErrorProvider(factory, option, logger);
97+
var result = await provider.Locate("223.91.188.112");
98+
Assert.Null(result);
99+
Assert.NotNull(provider.LastError);
100+
}
101+
88102
class MockProviderFetchError(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockProviderFetchError> logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
89103
{
90104
protected override Task<string?> Fetch(string url, HttpClient client, CancellationToken token) => throw new InvalidOperationException();
@@ -113,57 +127,41 @@ class MockProvider(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazo
113127
}
114128
}
115129

116-
class MockHttpNullMessageHandler : HttpMessageHandler
130+
class MockErrorProvider(IHttpClientFactory httpClientFactory, IOptions<BootstrapBlazorOptions> option, ILogger<MockErrorProvider> logger) : BaiduIpLocatorProvider(httpClientFactory, option, logger)
117131
{
118-
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
119-
{
120-
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
121-
{
122-
Content = new StringContent("null")
123-
});
124-
}
125-
}
126-
127-
class MockHttpSuccessMessageHandler : HttpMessageHandler
128-
{
129-
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
132+
protected override Task<string?> Fetch(string url, HttpClient client, CancellationToken token)
130133
{
131-
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
132-
{
133-
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\"}]}")
134-
});
134+
client = new HttpClient(new MockHttpExceptionMessageHandler(), true);
135+
return base.Fetch(url, client, token);
135136
}
136137
}
137138

138-
class MockHttpSuccessMessageHandlerV2 : HttpMessageHandler
139+
class MockHttpExceptionMessageHandler : HttpMessageHandler
139140
{
140141
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
141142
{
142-
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
143-
{
144-
Content = new StringContent("{\"code\":\"Success\",\"data\": {\"country\": \"中国\", \"prov\":\"省份\", \"city\":\"城市\", \"district\":\"区县\", \"isp\": \"测试\"}}")
145-
});
143+
throw new Exception("error test");
146144
}
147145
}
148146

149-
class MockHttpSuccessMessageHandlerJuHe : HttpMessageHandler
147+
class MockHttpNullMessageHandler : HttpMessageHandler
150148
{
151149
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
152150
{
153151
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
154152
{
155-
Content = new StringContent("{\"reason\": \"查询成功\", \"error_code\": 0, \"result\": {\"country\": \"中国\", \"prov\":\"省份\", \"city\":\"城市\", \"district\":\"区县\", \"isp\": \"测试\"}}")
153+
Content = new StringContent("null")
156154
});
157155
}
158156
}
159157

160-
class MockHttpFailedMessageHandlerJuHe : HttpMessageHandler
158+
class MockHttpSuccessMessageHandler : HttpMessageHandler
161159
{
162160
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
163161
{
164162
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
165163
{
166-
Content = new StringContent("{\"reason\": \"错误的请求KEY\", \"error_code\": 10001, \"result\": null}")
164+
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\"}]}")
167165
});
168166
}
169167
}

0 commit comments

Comments
 (0)