> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancestraldev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C# License Validation with Avalex (.NET / WPF)

> Validate Avalex software licenses in C# using HttpClient and System.Security.Cryptography. Works with .NET Core, WPF, and WinForms applications.

This guide shows you how to integrate Avalex license validation into a C# application targeting .NET Core, WPF, or WinForms. You will use the built-in `HttpClient` for the HTTP request, `System.Security.Cryptography.SHA256` for HWID hashing, and the `System.Text.Json` source-generation-friendly attributes for clean serialization — no third-party dependencies required.

## Full Example

The class below is self-contained and ready to add to any .NET project. Update `ApiUrl` and `ProductId` to match your deployment before shipping.

```csharp theme={null}
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

public class AvalexLicenseClient
{
    private static readonly HttpClient client = new HttpClient();
    private const string ApiUrl = "http://localhost:8080/licenses/validate";
    private const string ProductId = "prod_enterprise_2026";

    public class ValidateRequest
    {
        [JsonPropertyName("licenseId")]
        public string LicenseId { get; set; }
        [JsonPropertyName("productId")]
        public string ProductId { get; set; }
        [JsonPropertyName("hwid")]
        public string Hwid { get; set; }
    }

    public class ValidateResponse
    {
        [JsonPropertyName("valid")]
        public bool Valid { get; set; }
    }

    public static string GetHwid()
    {
        string raw = Environment.MachineName + Environment.UserName + Environment.ProcessorCount;
        using var sha256 = SHA256.Create();
        byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(raw));
        return BitConverter.ToString(bytes).Replace("-", "").Substring(0, 32);
    }

    public static async Task<bool> ValidateAsync(string licenseId)
    {
        var requestObj = new ValidateRequest
        {
            LicenseId = licenseId,
            ProductId = ProductId,
            Hwid = GetHwid()
        };
        try
        {
            var response = await client.PostAsJsonAsync(ApiUrl, requestObj);
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadFromJsonAsync<ValidateResponse>();
                return result?.Valid ?? false;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[Avalex Error] {ex.Message}");
        }
        return false;
    }
}
```

## Code Walkthrough

**HWID generation (`GetHwid`)**

`GetHwid` combines `Environment.MachineName`, `Environment.UserName`, and `Environment.ProcessorCount` into a single string and computes its SHA-256 hash using the built-in `SHA256.Create()` factory. The raw hash bytes are converted to an uppercase hex string and truncated to 32 characters. You can strengthen this by adding more stable identifiers (e.g., the motherboard serial number via WMI), but the combination above is sufficient for most desktop deployments.

**Typed request and response models**

`ValidateRequest` and `ValidateResponse` use `[JsonPropertyName]` attributes to map C# PascalCase properties to the camelCase JSON field names expected by the Avalex API. This approach is compatible with `System.Text.Json`'s source generator and avoids any dependency on `Newtonsoft.Json`.

**Async usage (`ValidateAsync`)**

`ValidateAsync` is a `Task<bool>` method, making it straightforward to `await` from any modern async entry point. The `PostAsJsonAsync` extension method serializes the request object and sets the `Content-Type` header automatically. If the HTTP response is successful, `ReadFromJsonAsync<ValidateResponse>` deserializes the body. Any exception — network failure, DNS error, timeout — is caught and logged, and the method returns `false` so your application defaults to a locked state on unexpected errors.

<Note>
  Replace `ApiUrl` with your production HTTPS endpoint before distributing your application. The `http://localhost:8080` address is for local development only.
</Note>

<Tip>
  For WPF or WinForms applications, call `ValidateAsync` from your startup window's `Loaded` event handler (or `Form.Load`) before making the main UI visible. This ensures users never see the application interface before their license has been confirmed.
</Tip>
