diff --git a/ByteGuard.FileValidator.Extensions.DependencyInjection.slnx b/ByteGuard.FileValidator.Extensions.DependencyInjection.slnx
index 52a773b..2bfe89c 100644
--- a/ByteGuard.FileValidator.Extensions.DependencyInjection.slnx
+++ b/ByteGuard.FileValidator.Extensions.DependencyInjection.slnx
@@ -1,3 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 0c543d4..8bee196 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,83 @@
# ByteGuard.FileValidator.Extensions.DependencyInjection 
+`ByteGuard.FileValidator.Extensions.DependencyInjection` provides first-class integration of `ByteGuard.FileValidator` with `Microsoft.Extensions.DependencyInjection`.
+
+It gives you:
+- Extension methods to register the file validator in the DI container
+- Easy configuration via appsettings.json or fluent configuration in code
+
+> This package is the `Microsoft.Extensions.DependencyInjection` integration layer.
+> The core validation logic lives in [`ByteGuard.FileValidator`](https://github.com/ByteGuard-HQ/byteguard-file-validator-net).
+
+## Getting Started
+
+### Installation
+This package is published and installed via NuGet.
+
+Reference the package in your project:
+```bash
+dotnet add package ByteGuard.FileValidator.Extensions.DependencyInjection
+```
+
+## Usage
+
+### Add to DI container
+In your `Program.cs` (or `Startup.cs` in older projects), register the validator:
+
+```csharp
+using ByteGuard.FileValidator;
+using ByteGuard.FileValidator.Extensions.DependencyInjection;
+
+// Using inline configuration
+builder.Services.AddFileValidator(options =>
+{
+ options.AllowFileTypes(FileExtensions.Pdf, FileExtensions.Jpg, FileExtensions.Png);
+ options.FileSizeLimit = ByteSize.MegaBytes(25);
+ options.ThrowOnInvalidFiles(false);
+});
+
+// Using configuration from appsettings.json
+builder.Services.AddFileValidator(options => configuration.GetSection("FileValidatorConfiguration").Bind(options));
+```
+
+### Injection & Usage
+You can then inject `FileValidator` into your services and other classes.
+
+```csharp
+public class MyService
+{
+ private readonly FileValidator _fileValidator;
+
+ public MyService(FileValidator fileValidator)
+ {
+ _fileValidator = fileValidator;
+ }
+
+ public bool SaveFile(Stream fileStream, string fileName)
+ {
+ var isValid = _fileValidator.IsValidFile(fileName, fileStream);
+
+ // ...
+ }
+}
+```
+
+### Configuration via appsettings
+It's possible to configure the `FileValidator` through `appsettings.json`.
+
+> _ℹ️ As you'll notice below, you can either define the `FileSizeLimit` in raw byte size, or use the `UnitFileSizeLimit` to define
+> the file size in a more human readable format. When both are defined, `FileSizeLimit` always wins over `UnitFileSizeLimit`._
+
+```json
+{
+ "FileValidatorConfiguration": {
+ "SupportedFileTypes": [ ".pdf", ".jpg", ".png" ],
+ "FileSizeLimit": 26214400,
+ "UnitFileSizeLimit": "25MB",
+ "ThrowExceptionOnInvalidFile": true
+ }
+}
+```
+
+## License
+_ByteGuard.FileValidator.Extensions.DpendencyInjection is Copyright © ByteGuard Contributors - Provided under the MIT license._
\ No newline at end of file
diff --git a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ByteGuard.FileValidator.Extensions.DependencyInjection.csproj b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ByteGuard.FileValidator.Extensions.DependencyInjection.csproj
index 45d1a79..7ea2af2 100644
--- a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ByteGuard.FileValidator.Extensions.DependencyInjection.csproj
+++ b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ByteGuard.FileValidator.Extensions.DependencyInjection.csproj
@@ -2,8 +2,8 @@
net8.0;net9.0;net10.0
- ByteGuard Contributors, detilium
- ByteGuard File Validator support for ASP.NET Core.
+ ByteGuard Contributors
+ ByteGuard File Validator support for Microsoft.Extensions.DependencyInjection.
https://github.com/ByteGuard-HQ/byteguard-file-validator-extensions-dependency-injection
https://github.com/ByteGuard-HQ/byteguard-file-validator-extensions-dependency-injection
git
diff --git a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorConfigurationOptionsValidator.cs b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorConfigurationOptionsValidator.cs
new file mode 100644
index 0000000..cbac2e7
--- /dev/null
+++ b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorConfigurationOptionsValidator.cs
@@ -0,0 +1,24 @@
+using ByteGuard.FileValidator.Configuration;
+using Microsoft.Extensions.Options;
+
+namespace ByteGuard.FileValidator.Extensions.DependencyInjection.Configuration;
+
+///
+/// File validator configuration options validator for use with the options pattern.
+///
+public class FileValidatorConfigurationOptionsValidator : IValidateOptions
+{
+ ///
+ public ValidateOptionsResult Validate(string? name, FileValidatorConfiguration config)
+ {
+ try
+ {
+ ConfigurationValidator.ThrowIfInvalid(config);
+ return ValidateOptionsResult.Success;
+ }
+ catch (Exception ex)
+ {
+ return ValidateOptionsResult.Fail(ex.Message);
+ }
+ }
+}
diff --git a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorSettingsConfiguration.cs b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorSettingsConfiguration.cs
index 01695e6..d368d9d 100644
--- a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorSettingsConfiguration.cs
+++ b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/Configuration/FileValidatorSettingsConfiguration.cs
@@ -1,6 +1,47 @@
namespace ByteGuard.FileValidator.Extensions.DependencyInjection.Configuration;
+///
+/// Appsettings specific configuration for the File Validator.
+///
public class FileValidatorSettingsConfiguration
{
+ ///
+ /// Supported file types.
+ ///
+ ///
+ /// Setup which file types are supported by the file validator.
+ /// File types should be specified with their leading dot, e.g. .jpg, .png, .pdf, etc.
+ /// Currently supported file types can be found in .
+ ///
+ public List SupportedFileTypes { get; set; } = new List();
+ ///
+ /// Maximum file size limit in bytes.
+ ///
+ ///
+ /// Defines the file size limit of files. See for conversion help.
+ ///
+ public long FileSizeLimit { get; set; } = -1;
+
+ ///
+ /// Maximum file size limit in unit string representation (e.g. "25MB", "2 GB", etc.).
+ ///
+ ///
+ /// Will be ignored if is defined.
+ /// Spacing ("25 MB" vs. "25MB") is irrelevant.
+ /// Supported string representation are:
+ ///
+ /// - B: Bytes
+ /// - KB: Kilobytes
+ /// - MB: Megabytes
+ /// - GB: Gigabytes
+ ///
+ ///
+ ///
+ public string? UnitFileSizeLimit { get; set; }
+
+ ///
+ /// Whether to throw an exception if an unsupported/invalid file is encountered. Defaults to true.
+ ///
+ public bool ThrowExceptionOnInvalidFile { get; set; } = true;
}
diff --git a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
index 817b2ba..b755b12 100644
--- a/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
+++ b/src/ByteGuard.FileValidator.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
@@ -1,12 +1,52 @@
+using ByteGuard.FileValidator.Configuration;
+using ByteGuard.FileValidator.Extensions.DependencyInjection.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
namespace ByteGuard.FileValidator.Extensions.DependencyInjection;
+///
+/// Extension methods for registering the File Validator services in an .
+///
public static class ServiceCollectionExtensions
{
- public static IServiceCollection AddFileValidator(this IServiceCollection services, Action configureSettings)
+ ///
+ /// Adds the File Validator services to the specified with custom configuration options.
+ ///
+ /// Service collection.
+ /// Configuration options.
+ public static IServiceCollection AddFileValidator(this IServiceCollection services, Action options)
{
- // TODO.
+ // Validate and setup configuration options.
+ services.AddSingleton,
+ FileValidatorConfigurationOptionsValidator>();
+
+ services.Configure(options);
+
+ services.AddOptions()
+ .Configure>((cfg, settings) =>
+ {
+ // Convert from FileValidatorSettingsConfiguration to FileValidatorConfiguration.
+ cfg.SupportedFileTypes = settings.Value.SupportedFileTypes;
+ cfg.ThrowExceptionOnInvalidFile = settings.Value.ThrowExceptionOnInvalidFile;
+
+ if (settings.Value.FileSizeLimit != -1)
+ {
+ cfg.FileSizeLimit = settings.Value.FileSizeLimit;
+ }
+ else if (!string.IsNullOrWhiteSpace(settings.Value.UnitFileSizeLimit))
+ {
+ cfg.FileSizeLimit = ByteSize.Parse(settings.Value.UnitFileSizeLimit);
+ }
+ })
+ .ValidateOnStart();
+
+ // Register the FileValidator service.
+ services.AddSingleton(serviceProvider =>
+ {
+ var configuration = serviceProvider.GetRequiredService>().Value;
+ return new FileValidator(configuration);
+ });
return services;
}
diff --git a/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/FileValidator.Extensions.DependencyInjection.Tests.Unit.csproj b/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/FileValidator.Extensions.DependencyInjection.Tests.Unit.csproj
new file mode 100644
index 0000000..f28e02b
--- /dev/null
+++ b/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/FileValidator.Extensions.DependencyInjection.Tests.Unit.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net10.0
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/ServiceCollectionExtensionsTests.cs b/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/ServiceCollectionExtensionsTests.cs
new file mode 100644
index 0000000..092c16a
--- /dev/null
+++ b/tests/FileValidator.Extensions.DependencyInjection.Tests.Unit/ServiceCollectionExtensionsTests.cs
@@ -0,0 +1,88 @@
+using ByteGuard.FileValidator.Configuration;
+using ByteGuard.FileValidator.Extensions.DependencyInjection.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace ByteGuard.FileValidator.Extensions.DependencyInjection.Tests.Unit;
+
+public class ServiceCollectionExtensionsTests
+{
+ [Fact(DisplayName = "AddFileValidator adds FileValidator to the service collection")]
+ public void AddFileValidator_AddsFileValidatorToServiceCollection()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+
+ // Act
+ services.AddFileValidator(config =>
+ {
+ config.SupportedFileTypes = new List() { ".png", ".jpg" };
+ config.UnitFileSizeLimit = "25MB";
+ });
+
+ var serviceProvider = services.BuildServiceProvider();
+
+ // Assert
+ var fileValidator = serviceProvider.GetService();
+ Assert.NotNull(fileValidator);
+ }
+
+ [Fact(DisplayName = "AddFileValidator should throws exception when configuration is invalid")]
+ public void AddFileValidator_ShouldThrowException_WhenConfigurationIsInvalid()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+
+ // Act
+ services.AddFileValidator(config =>
+ {
+ config.SupportedFileTypes = []; // Invalid configuration - missing supported file types
+ });
+
+ var serviceProvider = services.BuildServiceProvider();
+
+ // Assert
+ Assert.ThrowsAny(() => serviceProvider.GetRequiredService());
+ }
+
+ [Fact(DisplayName = "AddFileValidator should set correct file size limit when using the friendly file size limit property")]
+ public void AddFileValidator_FriendlyFileSizeLimitSet_ShouldAddAFileValidator()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ Action configAction = options =>
+ {
+ options.SupportedFileTypes = [".pdf"];
+ options.UnitFileSizeLimit = "25MB";
+ };
+
+ // Act
+ services.AddFileValidator(configAction);
+
+ // Assert
+ var sp = services.BuildServiceProvider();
+ var options = sp.GetRequiredService>();
+ Assert.Equal(ByteSize.MegaBytes(25), options.Value.FileSizeLimit);
+ }
+
+ [Fact(DisplayName = "AddFileValidator should use file size limit over friendly file size limit if both are set")]
+ public void AddFileValidator_FileSizeLimitAndFriendlyFileSizeLimitBothSet_ShouldUseFileSizeLimitOverFriendlyFileSizeLimit()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ Action configAction = options =>
+ {
+ options.SupportedFileTypes = [".pdf"];
+ options.FileSizeLimit = ByteSize.MegaBytes(10);
+ options.UnitFileSizeLimit = "25MB";
+ };
+
+ // Act
+ services.AddFileValidator(configAction);
+
+ // Assert
+ var sp = services.BuildServiceProvider();
+ var options = sp.GetRequiredService>();
+ Assert.Equal(ByteSize.MegaBytes(10), options.Value.FileSizeLimit);
+ }
+}