Skip to content

Commit 5b0b525

Browse files
committed
Prepare SGuard for initial release:
- Add NuGet metadata and icon files. - Introduce CONTRIBUTING.md for contribution guidelines. - Enhance documentation with badges and corrections. - Update source code for extensibility and multi-version .NET support.
1 parent 8e95971 commit 5b0b525

7 files changed

Lines changed: 136 additions & 34 deletions

File tree

CONTRIBUTING.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Contributing to SGuard.DataAnnotations
2+
3+
Thank you for your interest in contributing to SGuard! We welcome contributions from everyone. This guide will help you get started.
4+
5+
## How to Contribute
6+
7+
1. **Fork the repository**
8+
- Click the "Fork" button at the top of the GitHub page to create your own copy.
9+
2. **Clone your fork**
10+
- `git clone https://github.com/selcukgural/SGuard.DataAnnotations.git`
11+
3. **Create a branch**
12+
- `git checkout -b my-feature-branch`
13+
4. **Make your changes**
14+
- Add your improvements, bug fixes, or documentation updates.
15+
5. **Test your changes**
16+
- Ensure all tests pass and your code is robust.
17+
6. **Commit and push**
18+
- `git commit -am "Describe your change"`
19+
- `git push origin my-feature-branch`
20+
7. **Open a Pull Request**
21+
- Go to your fork on GitHub and click "New Pull Request."
22+
23+
## Code Style
24+
- Follow .NET and C# best practices.
25+
- Write clear, concise, and well-documented code.
26+
- Add XML comments for public APIs.
27+
28+
## Reporting Issues
29+
- Use GitHub Issues to report bugs, request features, or ask questions.
30+
- Please provide as much detail as possible.
31+
32+
## Community Standards
33+
- Be respectful and inclusive.
34+
- Follow the [Code of Conduct](.github/CODE_OF_CONDUCT.md).
35+
36+
## License
37+
By contributing, you agree that your contributions will be licensed under the MIT License.
38+
39+
---
40+
41+
Thank you for helping make SGuard.DataAnnotations better!

README.md

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
# SGuard.DataAnnotations
22

3+
![CI](https://github.com/selcukgural/SGuard.DataAnnotations/actions/workflows/ci.yml/badge.svg)
4+
[![NuGet Version](https://img.shields.io/nuget/v/SGuard.DataAnnotations.svg?style=flat-square)](https://www.nuget.org/packages/SGuard.DataAnnotations/)
5+
[![NuGet Downloads](https://img.shields.io/nuget/dt/SGuard.DataAnnotations.svg?style=flat-square)](https://www.nuget.org/packages/SGuard.DataAnnotations/)
6+
[![Coverage](https://codecov.io/gh/selcukgural/SGuard.DataAnnotations/branch/main/graph/badge.svg)](https://codecov.io/gh/selcukgural/SGuard.DataAnnotations)
7+
8+
39
**SGuard.DataAnnotations** provides localized and extensible DataAnnotations support for .NET, including:
410
- Localizable validation attributes (with robust fallback and custom error handling)
5-
- Collection, conditional, and property comparison validators not found in standard DataAnnotations
11+
- Collection, conditional, and property comparison validators are not found in standard DataAnnotations
612
- Guard pattern (`Is.*` for boolean return, `ThrowIf.*` for exception-throwing) for model validation
713
- Seamless integration with DataAnnotations and SGuard's fail-fast/callback philosophy
814
- Well-tested and extensible for real-world application scenarios
@@ -74,35 +80,34 @@ SGuard.DataAnnotations ships with built-in resource support for the following la
7480
> **Note:**
7581
> - If the current UI culture is not found, SGuard will fallback to English or to the fallback message if provided.
7682
> - You can add your own resource files to support additional languages.
77-
> - [How to add your own language?](#how-to-add-custom-language)
78-
83+
> - [How to add your own language?](#how-to-add-a-custom-language)
7984
---
8085

8186
## Supported Attributes
8287

8388
### String & Common Validators
8489

85-
| Attribute | Purpose | Supported Types | Example Usage |
86-
|----------------------------------------|-----------------------------------------------|-----------------------------------|---------------|
87-
| `SGuardRequiredAttribute` | Required field (localized) | Any | `[SGuardRequired(typeof(Resources.SGuardDataAnnotations), "Username_Required")]` |
88-
| `SGuardMinLengthAttribute` | Minimum string length | `string`, `array`, `ICollection` | `[SGuardMinLength(5, typeof(Resources.SGuardDataAnnotations), "Username_MinLength")]` |
89-
| `SGuardMaxLengthAttribute` | Maximum string length | `string`, `array`, `ICollection` | `[SGuardMaxLength(20, typeof(Resources.SGuardDataAnnotations), "Username_MaxLength")]` |
90-
| `SGuardStringLengthAttribute` | Min/max string length | `string` | `[SGuardStringLength(12, typeof(Resources.SGuardDataAnnotations), "Username_MaxLength")]` |
91-
| `SGuardRegularExpressionAttribute` | Regex pattern | `string` | `[SGuardRegularExpression("^[a-zA-Z0-9_]+$", typeof(Resources.SGuardDataAnnotations), "Username_InvalidCharacters")]` |
92-
| `SGuardEmailAddressAttribute` | Email format | `string` | `[SGuardEmailAddress(typeof(Resources.SGuardDataAnnotations), "Email_InvalidFormat")]` |
93-
| `SGuardPhoneAttribute` | Phone format | `string` | `[SGuardPhone(typeof(Resources.SGuardDataAnnotations), "Profile_Phone_Invalid")]` |
94-
| `SGuardUrlAttribute` | URL format | `string` | `[SGuardUrl(typeof(Resources.SGuardDataAnnotations), "Common_Url_Invalid")]` |
95-
| `SGuardCreditCardAttribute` | Credit card format | `string` | `[SGuardCreditCard(typeof(Resources.SGuardDataAnnotations), "Common_CreditCard_Invalid")]` |
96-
| `SGuardRangeAttribute` | Value must be within a numeric range | `int`, `double` | `[SGuardRange(1, 10, typeof(Resources.SGuardDataAnnotations), "Common_Range")]` |
90+
| Attribute | Purpose | Supported Types | Example Usage |
91+
|------------------------------------|--------------------------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------|
92+
| `SGuardRequiredAttribute` | Required field (localized) | Any | `[SGuardRequired(typeof(Resources.SGuardDataAnnotations), "Username_Required")]` |
93+
| `SGuardMinLengthAttribute` | Minimum string length | `string`, `array`, `ICollection` | `[SGuardMinLength(5, typeof(Resources.SGuardDataAnnotations), "Username_MinLength")]` |
94+
| `SGuardMaxLengthAttribute` | Maximum string length | `string`, `array`, `ICollection` | `[SGuardMaxLength(20, typeof(Resources.SGuardDataAnnotations), "Username_MaxLength")]` |
95+
| `SGuardStringLengthAttribute` | Min/max string length | `string` | `[SGuardStringLength(12, typeof(Resources.SGuardDataAnnotations), "Username_MaxLength")]` |
96+
| `SGuardRegularExpressionAttribute` | Regex pattern | `string` | `[SGuardRegularExpression("^[a-zA-Z0-9_]+$", typeof(Resources.SGuardDataAnnotations), "Username_InvalidCharacters")]` |
97+
| `SGuardEmailAddressAttribute` | Email format | `string` | `[SGuardEmailAddress(typeof(Resources.SGuardDataAnnotations), "Email_InvalidFormat")]` |
98+
| `SGuardPhoneAttribute` | Phone format | `string` | `[SGuardPhone(typeof(Resources.SGuardDataAnnotations), "Profile_Phone_Invalid")]` |
99+
| `SGuardUrlAttribute` | URL format | `string` | `[SGuardUrl(typeof(Resources.SGuardDataAnnotations), "Common_Url_Invalid")]` |
100+
| `SGuardCreditCardAttribute` | Credit card format | `string` | `[SGuardCreditCard(typeof(Resources.SGuardDataAnnotations), "Common_CreditCard_Invalid")]` |
101+
| `SGuardRangeAttribute` | Value must be within a numeric range | `int`, `double` | `[SGuardRange(1, 10, typeof(Resources.SGuardDataAnnotations), "Common_Range")]` |
97102

98103
### Collection Validators
99104

100-
| Attribute | Purpose | Supported Types | Example Usage |
101-
|--------------------------------------------|-----------------------------------------------------------------|-------------------------------|---------------|
102-
| `SGuardRequiredCollectionAttribute` | Collection must not be null/empty | `IEnumerable`, arrays, etc. | `[SGuardRequiredCollection(typeof(Resources.SGuardDataAnnotations), "Common_Collection_Required")]` |
103-
| `SGuardMinCountAttribute` | Minimum item count in collection | `IEnumerable`, arrays, etc. | `[SGuardMinCount(2, typeof(Resources.SGuardDataAnnotations), "Common_Collection_MinCount")]` |
104-
| `SGuardMaxCountAttribute` | Maximum item count in collection | `IEnumerable`, arrays, etc. | `[SGuardMaxCount(5, typeof(Resources.SGuardDataAnnotations), "Common_Collection_MaxCount")]` |
105-
| `SGuardCollectionItemsMatchAttribute` | Each item must match one/more validators (e.g. regex, required) | `IEnumerable`, arrays, etc. | `[SGuardCollectionItemsMatch(typeof(EmailAddressAttribute), typeof(Resources.SGuardDataAnnotations), "Email_InvalidFormat", AggregateAllErrors = true)]` |
105+
| Attribute | Purpose | Supported Types | Example Usage |
106+
|---------------------------------------|-----------------------------------------------------------------|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
107+
| `SGuardRequiredCollectionAttribute` | Collection must not be null/empty | `IEnumerable`, arrays, etc. | `[SGuardRequiredCollection(typeof(Resources.SGuardDataAnnotations), "Common_Collection_Required")]` |
108+
| `SGuardMinCountAttribute` | Minimum item count in collection | `IEnumerable`, arrays, etc. | `[SGuardMinCount(2, typeof(Resources.SGuardDataAnnotations), "Common_Collection_MinCount")]` |
109+
| `SGuardMaxCountAttribute` | Maximum item count in collection | `IEnumerable`, arrays, etc. | `[SGuardMaxCount(5, typeof(Resources.SGuardDataAnnotations), "Common_Collection_MaxCount")]` |
110+
| `SGuardCollectionItemsMatchAttribute` | Each item must match one/more validators (e.g. regex, required) | `IEnumerable`, arrays, etc. | `[SGuardCollectionItemsMatch(typeof(EmailAddressAttribute), typeof(Resources.SGuardDataAnnotations), "Email_InvalidFormat", AggregateAllErrors = true)]` |
106111

107112
**Details:**
108113
- `SGuardCollectionItemsMatchAttribute` can take multiple validators and will apply them to each item.
@@ -111,18 +116,18 @@ SGuard.DataAnnotations ships with built-in resource support for the following la
111116

112117
### Conditional Validators
113118

114-
| Attribute | Purpose | Supported Types | Example Usage |
115-
|----------------------------------|-------------------------------------------------|----------------|---------------|
116-
| `SGuardRequiredIfAttribute` | Field required if another property equals value | Any | `[SGuardRequiredIf("Country", "USA", typeof(Resources.SGuardDataAnnotations), "Address_Required")]` |
119+
| Attribute | Purpose | Supported Types | Example Usage |
120+
|-----------------------------|-------------------------------------------------|-----------------|-----------------------------------------------------------------------------------------------------|
121+
| `SGuardRequiredIfAttribute` | Field required if another property equals value | Any | `[SGuardRequiredIf("Country", "USA", typeof(Resources.SGuardDataAnnotations), "Address_Required")]` |
117122

118123
### Comparison Validators
119124

120-
| Attribute | Purpose | Supported Types | Example Usage |
121-
|-----------------------------------------|------------------------------------------|---------------------|---------------|
122-
| `SGuardCompareAttribute` | Values must be equal (like CompareAttribute) | Any | `[SGuardCompare("Password", typeof(Resources.SGuardDataAnnotations), "Password_Mismatch")]` |
123-
| `SGuardBetweenAttribute` | Value must be between two properties | IComparable types | `[SGuardBetween("Min", "Max", true, typeof(Resources.SGuardDataAnnotations), "Common_Between")]` |
124-
| `SGuardGreaterThanAttribute` | Value must be greater than another property | IComparable types | `[SGuardGreaterThan("MinAge", typeof(Resources.SGuardDataAnnotations), "Profile_BirthDate_MinimumAge")]` |
125-
| `SGuardLessThanAttribute` | Value must be less than another property | IComparable types | `[SGuardLessThan("MaxAge", typeof(Resources.SGuardDataAnnotations), "Profile_BirthDate_MaximumAge")]` |
125+
| Attribute | Purpose | Supported Types | Example Usage |
126+
|------------------------------|----------------------------------------------|-------------------|----------------------------------------------------------------------------------------------------------|
127+
| `SGuardCompareAttribute` | Values must be equal (like CompareAttribute) | Any | `[SGuardCompare("Password", typeof(Resources.SGuardDataAnnotations), "Password_Mismatch")]` |
128+
| `SGuardBetweenAttribute` | Value must be between two properties | IComparable types | `[SGuardBetween("Min", "Max", true, typeof(Resources.SGuardDataAnnotations), "Common_Between")]` |
129+
| `SGuardGreaterThanAttribute` | Value must be greater than another property | IComparable types | `[SGuardGreaterThan("MinAge", typeof(Resources.SGuardDataAnnotations), "Profile_BirthDate_MinimumAge")]` |
130+
| `SGuardLessThanAttribute` | Value must be less than another property | IComparable types | `[SGuardLessThan("MaxAge", typeof(Resources.SGuardDataAnnotations), "Profile_BirthDate_MaximumAge")]` |
126131

127132
**Supported types:** `int`, `double`, `decimal`, `DateTime`, `string`, etc. (anything implementing `IComparable`)
128133

@@ -184,7 +189,7 @@ SGuard.DataAnnotations ships with built-in resource support for the following la
184189
#### Exception Details
185190

186191
- Throws `DataAnnotationsException` by default, which contains all validation errors.
187-
- Extract errors (see also [`SGuard.DataAnnotations.Extensions`](src/Extensions/DataAnnotationsExceptionExtensions.cs)):
192+
- Extract errors (see also [`SGuard.DataAnnotations.Extensions`](./SGuard.DataAnnotations/src/Extensions/DataAnnotationsExceptionExtensions.cs)):
188193
```csharp
189194
catch (DataAnnotationsException ex)
190195
{
@@ -222,8 +227,8 @@ SGuard.DataAnnotations ships with built-in resource support for the following la
222227

223228
## Extending SGuard.DataAnnotations
224229

225-
Want to add your own fully-localized validation attribute?
226-
Just inherit from `SGuardValidationAttributeBase` and implement `IsValid`:
230+
Want to add your own fully localized validation attribute?
231+
Inherit from `SGuardValidationAttributeBase` and implement `IsValid`:
227232

228233
```csharp
229234
public class MyCustomLocalizedAttribute : SGuardValidationAttributeBase

SGuard.DataAnnotations.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1414
.gitignore = .gitignore
1515
CHANGELOG.md = CHANGELOG.md
1616
LICENSE = LICENSE
17+
CONTRIBUTING.md = CONTRIBUTING.md
1718
.github\CODE_OF_CONDUCT.md = .github\CODE_OF_CONDUCT.md
18-
.github\CONTRIBUTING.md = .github\CONTRIBUTING.md
1919
.github\SECURITY.md = .github\SECURITY.md
2020
README.md = README.md
2121
EndProjectSection

SGuard.DataAnnotations/SGuard.DataAnnotations.csproj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@
44
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
8+
<!-- NuGet Metadata -->
9+
<PackageId>SGuard.DataAnnotations</PackageId>
10+
<Version>0.1.0</Version>
11+
<Authors>Selçuk Güral</Authors>
12+
<Company>Selçuk Güral</Company>
13+
<Description>Advanced, extensible, and multilingual data validation and guard clause library for .NET. Includes custom validation attributes, guard helpers, and resource-based error messages for enterprise-grade applications.</Description>
14+
<PackageTags>validation;data-annotations;guard;multilingual;localization;attributes;.NET;enterprise;library</PackageTags>
15+
<PackageProjectUrl>https://github.com/selcukgural/SGuard.DataAnnotations</PackageProjectUrl>
16+
<RepositoryUrl>https://github.com/selcukgural/SGuard.DataAnnotations</RepositoryUrl>
17+
<RepositoryType>git</RepositoryType>
18+
<PackageLicenseUrl>https://opensource.org/licenses/MIT</PackageLicenseUrl>
19+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
20+
<PackageIcon>icon.png</PackageIcon>
21+
<Copyright>Copyright © 2025 Selçuk Güral</Copyright>
22+
<PackageReleaseNotes>Initial release. Supports .NET 6, 7, 8, 9. Multilingual validation, guard clauses, and CI/CD integration.</PackageReleaseNotes>
23+
<Title>SGuard.DataAnnotations - Advanced Multilingual Validation &amp; Guard Library for .NET
24+
</Title>
725
</PropertyGroup>
826

927
<ItemGroup>
7.68 KB
Loading
Lines changed: 19 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)