diff --git a/Directory.Packages.props b/Directory.Packages.props
index 72405c55cf..e74fc60a72 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -29,7 +29,7 @@
-
+
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
index bd767f93fb..cf9f128852 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
@@ -4,7 +4,6 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using DeviceDetectorNET;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
index d88febbfe9..886e1ed700 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
+++ b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
@@ -31,7 +31,7 @@
-
+
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
index 64fab10ac6..405e49753c 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting.StaticWebAssets;
using Microsoft.AspNetCore.RequestLocalization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
+using MyCSharp.HttpUserAgentParser.DependencyInjection;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Auditing;
@@ -59,6 +60,8 @@ public class AbpAspNetCoreModule : AbpModule
context.Services.AddAbpDynamicOptions();
StaticWebAssetsLoader.UseStaticWebAssets(context.Services.GetHostingEnvironment(), context.Services.GetConfiguration());
+
+ context.Services.AddHttpUserAgentCachedParser();
}
private static void AddAspNetServices(IServiceCollection services)
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs
index 6e450efbcd..b34a9752f7 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs
@@ -1,7 +1,8 @@
using System;
-using DeviceDetectorNET;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
+using MyCSharp.HttpUserAgentParser;
+using MyCSharp.HttpUserAgentParser.Providers;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.WebClientInfo;
@@ -11,13 +12,16 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
{
protected ILogger Logger { get; }
protected IHttpContextAccessor HttpContextAccessor { get; }
+ protected IHttpUserAgentParserProvider HttpUserAgentParser { get; }
public HttpContextWebClientInfoProvider(
ILogger logger,
- IHttpContextAccessor httpContextAccessor)
+ IHttpContextAccessor httpContextAccessor,
+ IHttpUserAgentParserProvider httpUserAgentParser)
{
Logger = logger;
HttpContextAccessor = httpContextAccessor;
+ HttpUserAgentParser = httpUserAgentParser;
}
public string? BrowserInfo => GetBrowserInfo();
@@ -46,27 +50,21 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
protected virtual string? GetDeviceInfo()
{
- string? deviceInfo = null;
- var deviceDetector = new DeviceDetector(GetBrowserInfo());
- deviceDetector.Parse();
- if (!deviceDetector.IsParsed())
+ var browserInfo = GetBrowserInfo();
+ if (browserInfo.IsNullOrWhiteSpace())
{
- return deviceInfo;
- }
-
- var osInfo = deviceDetector.GetOs();
- if (osInfo.Success)
- {
- deviceInfo = osInfo.Match.Name;
+ return null;
}
- var clientInfo = deviceDetector.GetClient();
- if (clientInfo.Success)
+ var httpUserAgentInformation = HttpUserAgentParser.Parse(browserInfo);
+ switch (httpUserAgentInformation.Type)
{
- deviceInfo = deviceInfo.IsNullOrWhiteSpace() ? clientInfo.Match.Name : deviceInfo + " " + clientInfo.Match.Name;
+ case HttpUserAgentType.Browser:
+ case HttpUserAgentType.Robot:
+ return (httpUserAgentInformation.Platform.HasValue ? httpUserAgentInformation.Platform.Value.Name + " " : string.Empty) + httpUserAgentInformation.Name;
+ case HttpUserAgentType.Unknown:
+ default:
+ return httpUserAgentInformation.UserAgent;
}
-
- return deviceInfo;
}
-
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs
index 641bbe03d7..0f9da48f68 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs
@@ -1,8 +1,8 @@
using System;
+using System.Linq;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
-using DeviceDetectorNET;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderDto.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderDto.cs
new file mode 100644
index 0000000000..85f96a65e3
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderDto.cs
@@ -0,0 +1,8 @@
+namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
+
+public class WebClientInfoProviderDto
+{
+ public string BrowserInfo { get; set; }
+
+ public string DeviceInfo { get; set; }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController.cs
new file mode 100644
index 0000000000..0d09c6e8ee
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController.cs
@@ -0,0 +1,26 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.WebClientInfo;
+
+namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
+
+[Route("api/web-client-info")]
+public class WebClientInfoProviderTestController : AbpController
+{
+ private IWebClientInfoProvider _webClientInfoProvider { get; }
+
+ public WebClientInfoProviderTestController(IWebClientInfoProvider webClientInfoProvider)
+ {
+ _webClientInfoProvider = webClientInfoProvider;
+ }
+
+ [HttpGet]
+ public Task GetAsync()
+ {
+ return Task.FromResult(new WebClientInfoProviderDto
+ {
+ BrowserInfo = _webClientInfoProvider.BrowserInfo,
+ DeviceInfo = _webClientInfoProvider.DeviceInfo
+ });
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController_Tests.cs
new file mode 100644
index 0000000000..0a5f13082b
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController_Tests.cs
@@ -0,0 +1,36 @@
+using System.Net;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
+
+public class WebClientInfoProviderTestController_Tests : AspNetCoreMvcTestBase
+{
+ [Theory]
+ [InlineData("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Windows 10 Chrome")]
+ [InlineData("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Mac OS X Chrome")]
+ [InlineData("PostmanRuntime/7.43.4", "PostmanRuntime/7.43.4")]
+ [InlineData("curl/7.64.1", "curl/7.64.1")]
+ [InlineData("Mozilla/5.0 (compatible; MojeekBot/0.11; +mojeek.com/bot.html)", "MojeekBot")]
+ public async Task TestAsync(string ua, string device)
+ {
+ var clientInfo = await GetWebClientInfoAsync(ua);
+ clientInfo.ShouldNotBeNull();
+ clientInfo.BrowserInfo.ShouldBe(ua);
+ clientInfo.DeviceInfo.ShouldBe(device);
+ }
+
+ private async Task GetWebClientInfoAsync(string userAgent )
+ {
+ using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "api/web-client-info"))
+ {
+ requestMessage.Headers.Add("User-Agent", userAgent);
+ var response = await Client.SendAsync(requestMessage);
+ response.StatusCode.ShouldBe(HttpStatusCode.OK);
+ return JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), JsonSerializerOptions.Web);
+ }
+ }
+}