Skip to content

Commit 8cccf77

Browse files
Conflict fixes
2 parents 3c01582 + 91d9190 commit 8cccf77

21 files changed

Lines changed: 967 additions & 10 deletions

.github/copilot-instructions.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# SignNow .NET SDK Development Guide
2+
3+
## Overview & Purpose
4+
5+
This is the official .NET SDK for SignNow's electronic signature API, targeting .NET Framework 4.6.2+, .NET Standard 2.0/2.1, and modern .NET versions. The SDK follows a service-oriented architecture and provides a simple, modern, and efficient way to interact with the SignNow API.
6+
7+
## High-Level Architecture
8+
9+
This SDK is designed as cross-platform library with service-oriented architecture, supporting asynchronous programming patterns and strong typing.
10+
11+
- **Project Type**: Class Library targeting multiple frameworks
12+
- **Architecture**: Service-oriented with clear separation of concerns
13+
- **Distribution**: Available via NuGet package manager
14+
- **Target Frameworks**: Multi-targeted for `.NET Core` and `.NET Framework 4.6.2` with support of standards - .NET Standard 2.0/2.1
15+
- **Key Design Patterns**:
16+
- **Dependency Injection (DI)**: The SDK is designed to be easily integrated into DI containers with minimal configuration (`SignNowContext` as the main entry point).
17+
- **Service Layer**: Core services are exposed via interfaces and represented by concrete classes in the `Service` folder.
18+
- **Model Layer**: Comprehensive model classes represent API requests and responses, ensuring strong typing and JSON serialization.
19+
- **Infrastructure Layer**: HTTP client infrastructure, including request/response handling, exceptions handling is encapsulated in base classes.
20+
- **Async/Await**: Full support for asynchronous operations with cancellation tokens.
21+
- **Token Management**: Built-in support for OAuth2 authentication, including token acquisition and refresh mechanisms.
22+
23+
## Solution & Project Structure
24+
25+
```
26+
├── SignNow.Net/ // Main SDK library
27+
│ ├── _Internal/
28+
│ │ ├── Constants/ // API endpoint URLs, error messages, and other constants
29+
│ │ ├── Extensions/ // Extension methods for string manipulation, validation, etc.
30+
│ │ ├── Helpers/ // Utility classes for HTTP requests, serialization, validation
31+
| | │ ├── Converters/ // Custom JSON converters for complex types (e.g., Uri, Enums)
32+
│ │ ├── Infrastructure/ // Telemetry and platform-specific implementations
33+
│ │ ├── Model/ // Internal model classes not exposed publicly
34+
│ │ └── Requests/ // Internal request classes for complex operations
35+
│ ├── Exceptions/ // Custom exception classes for API errors
36+
│ ├── Interfaces/ // Public service interfaces
37+
│ ├── Model/ // All model classes for API requests/responses
38+
│ │ ├── ComplexTags/ // Complex tag types (e.g., SignatureTag, TextTag, etc.)
39+
│ │ ├── EditFields/ // Edit field types (e.g., TextField, CheckboxField, etc.)
40+
│ │ ├── FieldContents/ // Field content types (e.g., TextContent, CheckboxContent, etc.)
41+
│ │ ├── Requests/ // Request model classes
42+
│ │ └── Responses/ // Response model classes
43+
│ ├── Service/ // Service implementations
44+
│ │ ├── DocumentGroupService.cs // Document group operations service
45+
│ │ ├── DocumentService.cs // Document operations service
46+
│ │ ├── EventSubscriptionService.cs // Event subscription service
47+
│ │ ├── FolderService.cs // Folder management service
48+
│ │ ├── OAuth2Service.cs // OAuth2 token management service
49+
│ │ ├── SignNowClient.cs // Core HTTP client implementation
50+
│ │ ├── UserService.cs // User management service
51+
│ │ └── WebClientBase.cs // Base class for HTTP clients
52+
│ ├── SignNowContext.cs // Main entry point and DI container setup
53+
│ └── SignNow.Net.csproj // Multi-target SDK project file (.NET Framework 4.6.2+, .NET Standard 2.0/2.1)
54+
55+
├── SignNow.Net.Examples/ // Usage examples and samples
56+
│ ├── Document group/ // Document group operations examples
57+
│ ├── Documents/ // Document operations examples
58+
│ ├── Folders/ // Folder management examples
59+
| ├── Invites/ // Event subscription examples
60+
│ ├── OAuth2/ // OAuth2 authentication examples
61+
│ ├── Template/ // Template management examples
62+
│ ├── TestExamples/ // Sample documents and templates for testing
63+
│ ├── Users/ // User management examples
64+
│ ├── Webhooks/ // Webhook management examples
65+
│ ├── ExamplesBase.cs // Base class for examples with common setup
66+
│ └── SignNow.Net.Examples.csproj // Example project file
67+
68+
├── SignNow.Net.Test/ // Comprehensive test suite
69+
│ ├── AcceptanceTests/ // End-to-end acceptance tests
70+
│ ├── Constants/ // Test constants (e.g., error messages, test user IDs)
71+
│ ├── Context/ // Tests for Credentials loading and SignNowContext setup
72+
│ ├── FeatureTests/ // Feature-specific integration tests
73+
│ ├── TestData/ // Test fixtures and sample data
74+
│ │ ├── Documents/ // Sample documents for testing
75+
│ │ └── FakeModels // Fake model classes for generating test data
76+
│ ├── UnitTests/ // Unit tests with no external dependencies
77+
│ ├── AssertExtensions.cs // Custom assertion extensions for tests
78+
│ ├── AuthorizedApiTestBase.cs // Base class for tests requiring authorized API access
79+
│ ├── Directory.Build.props // Shared MSBuild properties for tests
80+
│ ├── SignNowTestBase.cs // Base class for all tests with common setup/teardown
81+
│ ├── SignNow.Net.Test.csproj // Test project targeting multiple frameworks
82+
│ └── TestUtils.cs // Utility methods for tests (e.g., JSON serialization)
83+
84+
├── .editorconfig // Code formatting and style rules
85+
├── .netconfig // .NET runtime configuration (ReportGenerator configuration for codecoverage)
86+
├── CHANGELOG.md // SDK change log and release notes
87+
├── Directory.Build.props // Shared MSBuild properties and versioning
88+
├── netfx.props // .NET Framework specific build properties for multi-targeting and cross-platform support
89+
├── SignNow.Net.sln // Main solution file
90+
├── SignNow.props // Shared build properties for multi-targeting, versioning, and packaging (Nuget config)
91+
└── README.md // SDK documentation and getting started guide
92+
```
93+
94+
## Core Concepts & Implementation Details
95+
96+
### Public API Surface
97+
98+
- The public API is primarily defined by interfaces located in the `SignNow.Net/Interfaces` folder.
99+
- Consumers of the SDK should only need to depend on these interfaces and the models they expose.
100+
- All implementation classes with complex request transformations should be marked as `internal` and placed into `SignNow.Net/_Internal` folder.
101+
- All the public responses and request models are located in the `SignNow.Net/Model` folder.
102+
- All the entities of the SignNow API should be represented by strongly typed models. Models should be grouped by feature areas (e.g., `Document`, `User`, `Folder`, etc.) and further subdivided into `Requests` and `Responses` folders.
103+
- SignNow API entities could be grouped for re-usage purposes (e.g., `ComplexTags`, `EditFields`, `FieldContents`). The groups should be placed into separate folders under `Model` folder and represent single SignNow API entity.
104+
- Avoid exposing implementation details, such as HTTP client classes or internal helpers, in the public API.
105+
- For dynamic API responses, use internal Json converters to handle deserialization without exposing complexity to consumers.
106+
107+
### Dependency Injection
108+
109+
- The SDK provides a single entry point - `SignNowContext` with minimalistic parameters for configuration, like API base URL, Token (if any exists) and HTTP client.
110+
- This `SignNowContext` class registers all necessary services with a single context.
111+
- For User Authentication - use `SignNowContext.SetAppCredentials()` and `SignNowContext.GetAccessToken()` methods to configure application and user credentials respectively.
112+
- For advanced scenarios or re-usage of existing HTTP clients, the SDK provides an ability to set custom `ISignNowClient` implementation via `SignNowContext` constructor.
113+
- Application secrets and user credentials are not stored in the SDK, and should be managed by the consumer application.
114+
115+
### Platform-Specific Code
116+
117+
- The SDK targets multiple frameworks: .NET Framework 4.6.2, .NET Standard 2.0/2.1, and modern .NET versions (e.g., .NET 7.0/8.0).
118+
- To compile .NET SDK 2.x projects targeting .NET 4.x on Mono (Linux, macOS), we use `netfx.props` file with specific build properties for MSBuild system.
119+
- We use preprocessor directives (`#if NETSTANDARD`, `#if NET462`, `#if NETFRAMEWORK`) to compile code conditionally for each target.
120+
- Platform-specific and Framework-specific code is most commonly used for networking (e.g., `HttpClient` configuration) or file system differences.
121+
- All the business logic should be platform-agnostic and reusable across all target frameworks.
122+
- We use `System.Net.ServicePointManager` to enforce TLS 1.2 on .NET Framework 4.6.2, as it defaults to older protocols.
123+
124+
### Error Handling
125+
126+
- Exception handling should be consistent across platforms, with custom exceptions defined in the `Exceptions` folder.
127+
- The SDK throws own custom exceptions `SignNowException` with all the inner Exceptions and their details.
128+
- The SDK throws `ArgumentException`, `ArgumentNullException` for invalid method arguments or state.
129+
- Consumers should `try-catch` these specific exceptions to handle SDK-related errors gracefully.
130+
- Avoid throwing generic exceptions like `System.Exception` or specific for json conversion exception `JsonSerializationException`. All the exceptions should be wrapped into `SignNowException` with all the inner exceptions preserved.
131+
132+
## Coding & Contribution Guidelines
133+
134+
- **Style**: Follow the standard .NET coding conventions. Use the `.editorconfig` file provided in the repository.
135+
- **Testing**: Any new feature or bug fix must be accompanied by corresponding unit tests.
136+
- **Documentation**: All public types, methods, and properties must have XML documentation comments (`///`).
137+
- **Dependencies**: Minimize external dependencies. Before adding a new NuGet package, discuss it with the team.
138+
- **Change Log**: Update `CHANGELOG.md` with a summary of changes for each release and pull request.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
applyTo: '**/*.cs'
3+
description: Guidelines for building C# applications
4+
---
5+
6+
# C# Development
7+
8+
## C# Instructions
9+
10+
- Always use the specified version C#, this project is limited to C# 8.0 features.
11+
12+
## General Instructions
13+
14+
- Make only high confidence suggestions when reviewing code changes.
15+
16+
## Naming Conventions
17+
18+
- Follow PascalCase for component names, method names, and public members.
19+
- Use camelCase for private fields and local variables.
20+
- Prefix interface names with "I" (e.g., IUserService).
21+
22+
## Formatting
23+
24+
- Apply code-formatting style defined in `.editorconfig`.
25+
- Prefer file-scoped namespace declarations and single-line using directives.
26+
- Insert a newline before the opening curly brace of any code block (e.g., after if, for, while, foreach, using, try, etc.).
27+
- Ensure that the final return statement of a method is on its own line.
28+
- Use pattern matching and switch expressions wherever possible.
29+
- Use `nameof` instead of string literals when referring to member names.
30+
- Ensure that XML doc comments are created for any public APIs. When applicable, include `<example>` and `<code>` documentation in the comments.
31+
32+
## Nullable Reference Types
33+
34+
- Declare variables non-nullable, and check for null at entry points.
35+
- Use `default` instead of `null` for method parameters to follow type safety best practices.
36+
37+
## Testing
38+
39+
- Always include test cases for critical paths of the application.
40+
- Guide users through creating unit tests.
41+
- Omit "Act", "Arrange" or "Assert" comments.
42+
43+
## Performance Optimization
44+
45+
- Guide users on implementing caching strategies (in-memory, distributed, response caching).
46+
- Explain asynchronous programming patterns and why they matter for API performance.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
description: 'Guidance for working with .NET Framework and .NET Core projects. Includes project structure, C# language version, NuGet management, and best practices.'
3+
applyTo: '**/*.csproj, **/*.cs'
4+
---
5+
6+
# .NET Framework/Core Development
7+
8+
## Build and Compilation Requirements
9+
10+
- Always use `dotnet build` to build the solution or projects instead of `msbuild /t:rebuild`
11+
12+
## .NET SDK project Structure for .NET Framework and .NET Core compatibility
13+
14+
.NET Framework projects use the legacy project format, which differs significantly from modern SDK-style projects.
15+
This project - is SDK-style and supports multi-targeting for .NET Framework and .NET Core.
16+
17+
When working with such projects, consider the following structure:
18+
19+
- **Target Framework**: Uses `<TargetFramework>` instead of `<TargetFrameworkVersion>`
20+
- Example: `<TargetFrameworks>netstandard2.0;netstandard2.1;net462</TargetFrameworks>`
21+
- **Build Configuration**: Contains explicit `<PropertyGroup>` sections for common groups of configurations
22+
- **Package References**: Uses `<PackageReference>` instead of `packages.config` for NuGet dependencies
23+
- **Conditional Compilation**: Uses `#if NETFRAMEWORK` and `#if NETSTANDARD` for framework-specific code
24+
- **Conditional Package References**: Uses `Condition` attributes on `<PackageReference>` to include/exclude packages based on the target framework
25+
- Example:
26+
```xml
27+
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
28+
<PackageReference Include="SomeLegacyPackage" Version="1.0.0" />
29+
<Reference Include="System.Net.Http" />
30+
</ItemGroup>
31+
```
32+
- **Assembly Info**: Uses `<GenerateAssemblyInfo>` to control automatic generation of assembly attributes
33+
- Example: `<GenerateAssemblyInfo>false</GenerateAssemblyInfo>`
34+
- **Common Properties**: Centralizes common properties like `Company`, `Authors`, `Version` and Nuget package properties in a single `<PropertyGroup>` should be defined once for all target frameworks in `SignNow.props` file. This file should be included in all projects using `<Import Project="..\SignNow.props" />`.
35+
36+
## NuGet Package Management
37+
38+
- Installing and updating NuGet packages in .NET Framework projects is a complex task requiring coordinated changes to multiple files. Therefore, **do not attempt to install or update NuGet packages** in this project.
39+
- Instead, if changes to NuGet references are required, ask the user to install or update NuGet packages using the Visual Studio NuGet Package Manager or Visual Studio package manager console.
40+
- When recommending NuGet packages, ensure they are compatible with .NET Framework or .NET Standard 2.0 (not only .NET Core or .NET 5+).
41+
42+
## Environment Considerations (Cross-platform environment)
43+
44+
- Use Unix-style paths with forward slashes (e.g., `/path/to/file.cs`) and ensure compatibility with both Windows and Unix-like systems.
45+
- Use `dotnet` CLI commands for building, testing, and managing projects instead of Windows
46+
- Avoid Windows-specific commands and tools (e.g., PowerShell scripts, batch files)
47+
- Use Unix-appropriate commands when suggesting terminal operations
48+
- Consider Unix-specific behaviors when working with file system operations
49+
50+
## Common .NET Framework/Core agreements and Best Practices
51+
52+
### Async/Await Patterns
53+
- **ConfigureAwait(false)**: Always use `ConfigureAwait(false)` in library code to avoid deadlocks:
54+
```csharp
55+
var result = await SomeAsyncMethod().ConfigureAwait(false);
56+
```
57+
- **Avoid sync-over-async**: Don't use `.Result` or `.Wait()` or `.GetAwaiter().GetResult()`. These sync-over-async patterns can lead to deadlocks and poor performance. Always use `await` for asynchronous calls.
58+
59+
### DateTime Handling
60+
61+
- **Use DateTimeOffset for timestamps**: Prefer `DateTimeOffset` over `DateTime` for absolute time points
62+
- **Specify DateTimeKind**: When using `DateTime`, always specify `DateTimeKind.Utc`
63+
- **Culture-aware formatting**: Use `CultureInfo.InvariantCulture` for serialization/parsing
64+
65+
### Memory Management
66+
67+
- **Dispose pattern**: Implement `IDisposable` properly for unmanaged resources
68+
- **Using statements**: Always wrap `IDisposable` objects in using statements
69+
- **Avoid large object heap**: Keep objects under 85KB to avoid LOH allocation

0 commit comments

Comments
 (0)