Jak używać Fluent Validation z IronPDF w C#
Czym jest Fluent Validation?
FluentValidation to biblioteka walidacyjna .NET, która pomaga w tworzeniu reguł walidacji silnie typowanych. Wykorzystuje płynny interfejs i wyrażenia lambda, dzięki czemu kod jest bardziej czytelny i łatwiejszy w utrzymaniu. Zamiast używać adnotacji danych lub ręcznej walidacji w klasach modeli, możesz skorzystać z Fluent Validation, aby zbudować oddzielną klasę dla logiki walidacji.
Fluent Validation zapewnia większą elastyczność w zakresie walidacji. Dzięki wbudowanym walidatorom dla typowych scenariuszy, możliwości tworzenia niestandardowych walidacji oraz prostemu sposobowi łączenia reguł walidacji, Fluent Validation jest potężnym narzędziem w zestawie narzędzi .NET Core.
Zrozumienie płynnej walidacji
Fluent Validation to biblioteka open source dla platformy .NET, która ułatwia tworzenie reguł walidacji dla klas modeli.
- Walidatory: Walidatory to klasy, które hermetyzują logikę walidacji. They are typically created by inheriting from the
AbstractValidator<t>base class. - Reguły: Reguła to warunek walidacji, który musi spełniać dana właściwość. Rules are defined using the
RuleFormethod in a validator class. - Validation Failures: If a rule fails, Fluent Validation creates a
ValidationFailureobject that contains details about the error, including the property name and error message.
Czym jest IronPDF?
IronPDF - Convert HTML to PDF in C# to potężna biblioteka .NET, która pozwala generować dokumenty PDF na podstawie treści HTML. Niezależnie od tego, czy potrzebujesz tworzyć faktury, raporty czy jakikolwiek inny rodzaj dokumentu, IronPDF zapewnia łatwe w użyciu rozwiązanie. Integruje się płynnie z aplikacjami .NET Core, umożliwiając generowanie wysokiej jakości plików PDF za pomocą zaledwie kilku linii kodu.
Korzystanie z Fluent Validation z IronPDF
Teraz, gdy wiemy już, czym są Fluent Validation i IronPDF, zobaczmy, jak można je wykorzystać razem. Ten samouczek pomoże w stworzeniu generatora faktur, w którym zawartość faktury będzie sprawdzana przy użyciu FluentValidation w ASP.NET Core przed wygenerowaniem pliku PDF za pomocą IronPDF.
Konfiguracja projektu
Na początek utwórzmy nową aplikację konsolową w Visual Studio lub innym preferowanym środowisku programistycznym.
- Otwórz Visual Studio i przejdź do Plik > Nowy > Projekt.
-
Wybierz "Aplikacja konsolowa (ASP.NET Core)" jako szablon projektu i nadaj nazwę swojemu projektowi.
Utwórz nową aplikację konsolową -
Kliknij przycisk Dalej i skonfiguruj projekt, nadając mu nazwę oraz wybierając lokalizację repozytorium.
Skonfiguruj nową aplikację -
Kliknij przycisk Dalej i wybierz .NET Framework. Zalecane jest użycie najnowszej wersji .NET Framework (7).
Wybór platformy .NET Framework - Kliknij przycisk Utwórz, aby utworzyć projekt.
Zainstaluj wymagane pakiety
Po utworzeniu projektu dodaj niezbędne pakiety NuGet dla Fluent Validation i IronPDF.
- Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz opcję "Zarządzaj pakietami NuGet".
-
Wyszukaj "FluentValidation" i kliknij "Zainstaluj", aby dodać pakiet do swojego projektu.
Zainstaluj pakiet FluentValidation w interfejsie użytkownika menedżera pakietów NuGet - Podobnie, wyszukaj "IronPDF – Potężna biblioteka PDF dla .NET" i zainstaluj pakiet IronPDF.
Alternatywnie można zainstalować IronPDF za pomocą konsoli NuGet Package Manager Console, używając następującego polecenia:
Install-Package IronPdf
Zainstaluj pakiet IronPdf w konsoli menedżera pakietów
Po skonfigurowaniu projektu i zainstalowaniu wymaganych pakietów przejdźmy do zdefiniowania klasy treści PDF.
Określenie treści pliku PDF
In this example, a simple invoice PDF will be created from the HTML codes in two classes: InvoiceContent and InvoiceItem.
using System.Collections.Generic;
using System.Linq;
public abstract class PdfContent
{
// Abstract method to generate the HTML string
public abstract string RenderHtml();
}
public class InvoiceContent : PdfContent
{
public string CustomerName { get; set; }
public string Address { get; set; }
public List<InvoiceItem> InvoiceItems { get; set; }
// Constructs the HTML representation of the invoice
public override string RenderHtml()
{
string invoiceItemsHtml = string.Join("", InvoiceItems.Select(item => $"<li>{item.Description}: {item.Price}</li>"));
return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>";
}
}
public class InvoiceItem
{
public string Description { get; set; }
public decimal Price { get; set; }
}
using System.Collections.Generic;
using System.Linq;
public abstract class PdfContent
{
// Abstract method to generate the HTML string
public abstract string RenderHtml();
}
public class InvoiceContent : PdfContent
{
public string CustomerName { get; set; }
public string Address { get; set; }
public List<InvoiceItem> InvoiceItems { get; set; }
// Constructs the HTML representation of the invoice
public override string RenderHtml()
{
string invoiceItemsHtml = string.Join("", InvoiceItems.Select(item => $"<li>{item.Description}: {item.Price}</li>"));
return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>";
}
}
public class InvoiceItem
{
public string Description { get; set; }
public decimal Price { get; set; }
}
Imports System.Collections.Generic
Imports System.Linq
Public MustInherit Class PdfContent
' Abstract method to generate the HTML string
Public MustOverride Function RenderHtml() As String
End Class
Public Class InvoiceContent
Inherits PdfContent
Public Property CustomerName() As String
Public Property Address() As String
Public Property InvoiceItems() As List(Of InvoiceItem)
' Constructs the HTML representation of the invoice
Public Overrides Function RenderHtml() As String
Dim invoiceItemsHtml As String = String.Join("", InvoiceItems.Select(Function(item) $"<li>{item.Description}: {item.Price}</li>"))
Return $"<h1>Invoice for {CustomerName}</h1><p>{Address}</p><ul>{invoiceItemsHtml}</ul>"
End Function
End Class
Public Class InvoiceItem
Public Property Description() As String
Public Property Price() As Decimal
End Class
In the code above, an abstract PdfContent class is defined with an abstract method called RenderHtml. The InvoiceContent class extends PdfContent and represents the content of the invoice PDF. Zawiera pola dotyczące nazwy klienta, adresu oraz listy pozycji na fakturze. The InvoiceItem class contains two properties: 'Description' and 'Price'. The RenderHtml method generates the HTML markup for the invoice based on the content.
Teraz, gdy zawartość pliku PDF została zdefiniowana, przejdźmy do tworzenia reguł walidacji przy użyciu Fluent Validation.
Tworzenie reguł walidacji
For building validation rules for the InvoiceContent class, create a validator class called InvoiceContentValidator. This class will inherit from AbstractValidator<InvoiceContent>, which is provided by FluentValidation.
using FluentValidation;
public class InvoiceContentValidator : AbstractValidator<InvoiceContent>
{
public InvoiceContentValidator()
{
RuleFor(content => content.CustomerName).NotEmpty().WithMessage("Customer name is required.");
RuleFor(content => content.Address).NotEmpty().WithMessage("Address is required.");
RuleFor(content => content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.");
RuleForEach(content => content.InvoiceItems).SetValidator(new InvoiceItemValidator());
}
}
public class InvoiceItemValidator : AbstractValidator<InvoiceItem>
{
public InvoiceItemValidator()
{
RuleFor(item => item.Description).NotEmpty().WithMessage("Description is required.");
RuleFor(item => item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.");
}
}
using FluentValidation;
public class InvoiceContentValidator : AbstractValidator<InvoiceContent>
{
public InvoiceContentValidator()
{
RuleFor(content => content.CustomerName).NotEmpty().WithMessage("Customer name is required.");
RuleFor(content => content.Address).NotEmpty().WithMessage("Address is required.");
RuleFor(content => content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.");
RuleForEach(content => content.InvoiceItems).SetValidator(new InvoiceItemValidator());
}
}
public class InvoiceItemValidator : AbstractValidator<InvoiceItem>
{
public InvoiceItemValidator()
{
RuleFor(item => item.Description).NotEmpty().WithMessage("Description is required.");
RuleFor(item => item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.");
}
}
Imports FluentValidation
Public Class InvoiceContentValidator
Inherits AbstractValidator(Of InvoiceContent)
Public Sub New()
RuleFor(Function(content) content.CustomerName).NotEmpty().WithMessage("Customer name is required.")
RuleFor(Function(content) content.Address).NotEmpty().WithMessage("Address is required.")
RuleFor(Function(content) content.InvoiceItems).NotEmpty().WithMessage("At least one invoice item is required.")
RuleForEach(Function(content) content.InvoiceItems).SetValidator(New InvoiceItemValidator())
End Sub
End Class
Public Class InvoiceItemValidator
Inherits AbstractValidator(Of InvoiceItem)
Public Sub New()
RuleFor(Function(item) item.Description).NotEmpty().WithMessage("Description is required.")
RuleFor(Function(item) item.Price).GreaterThanOrEqualTo(0).WithMessage("Price must be greater than or equal to 0.")
End Sub
End Class
In the source code, the InvoiceContentValidator class is defined, which inherits from AbstractValidator<InvoiceContent>. Inside the constructor of the validator class, the RuleFor method defines validation rules for each property of the InvoiceContent class.
For example, RuleFor(content => content.CustomerName) specifies that the customer name should not be empty. Podobnie zdefiniowano reguły walidacji dla właściwości pozycji adresu i faktury.
The RuleForEach method iterates over each item in the InvoiceItems list and applies the InvoiceItemValidator. The InvoiceItemValidator class contains validation rules for the InvoiceItem class.
Mając te zasady walidacji, przejdźmy do generowania pliku PDF przy użyciu IronPDF.
Generowanie plików PDF za pomocą IronPDF
IronPDF – Generowanie i edycja dokumentów PDF to popularna biblioteka .NET służąca do tworzenia i edycji dokumentów PDF. Do wygenerowania pliku PDF na podstawie zweryfikowanej treści faktury zostanie użyty IronPDF.
using IronPdf;
using FluentValidation;
public class PdfService
{
// Generates a PDF document for the provided content
public PdfDocument GeneratePdf<t>(T content) where T : PdfContent
{
// Validate the content using the appropriate validator
var validator = GetValidatorForContent(content);
var validationResult = validator.Validate(content);
// Check if validation is successful
if (!validationResult.IsValid)
{
throw new FluentValidation.ValidationException(validationResult.Errors);
}
// Generate the PDF using IronPDF
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(content.RenderHtml());
}
// Retrieves the appropriate validator for the content
private IValidator<t> GetValidatorForContent<t>(T content) where T : PdfContent
{
if (content is InvoiceContent)
{
return (IValidator<t>)new InvoiceContentValidator();
}
else
{
throw new NotSupportedException("Unsupported content type.");
}
}
}
using IronPdf;
using FluentValidation;
public class PdfService
{
// Generates a PDF document for the provided content
public PdfDocument GeneratePdf<t>(T content) where T : PdfContent
{
// Validate the content using the appropriate validator
var validator = GetValidatorForContent(content);
var validationResult = validator.Validate(content);
// Check if validation is successful
if (!validationResult.IsValid)
{
throw new FluentValidation.ValidationException(validationResult.Errors);
}
// Generate the PDF using IronPDF
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(content.RenderHtml());
}
// Retrieves the appropriate validator for the content
private IValidator<t> GetValidatorForContent<t>(T content) where T : PdfContent
{
if (content is InvoiceContent)
{
return (IValidator<t>)new InvoiceContentValidator();
}
else
{
throw new NotSupportedException("Unsupported content type.");
}
}
}
Imports IronPdf
Imports FluentValidation
Public Class PdfService
' Generates a PDF document for the provided content
Public Function GeneratePdf(Of T As PdfContent)(content As T) As PdfDocument
' Validate the content using the appropriate validator
Dim validator = GetValidatorForContent(content)
Dim validationResult = validator.Validate(content)
' Check if validation is successful
If Not validationResult.IsValid Then
Throw New FluentValidation.ValidationException(validationResult.Errors)
End If
' Generate the PDF using IronPDF
Dim renderer = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(content.RenderHtml())
End Function
' Retrieves the appropriate validator for the content
Private Function GetValidatorForContent(Of T As PdfContent)(content As T) As IValidator(Of T)
If TypeOf content Is InvoiceContent Then
Return CType(New InvoiceContentValidator(), IValidator(Of T))
Else
Throw New NotSupportedException("Unsupported content type.")
End If
End Function
End Class
The PdfService class provides a GeneratePdf method. This method takes a PdfContent object as input and generates the PDF document based on the validated content.
First, it retrieves the appropriate validator for the content by calling the GetValidatorForContent method, which checks the type of content and returns the corresponding validator. In our case, we support InvoiceContent and use the InvoiceContentValidator.
Next, the content is validated using the validator by calling its Validate method. The validation result is stored in a ValidationResult object.
If the validation fails (!validationResult.IsValid), a FluentValidation.ValidationException is thrown with the validation errors. Otherwise, the PDF is generated using IronPDF.
An instance of ChromePdfRenderer is created to render the HTML content as a PDF. The RenderHtmlAsPdf method is called on the renderer object, passing in the HTML generated by the content.RenderHtml method, generating the PDF document.
Now that we have defined the PDF generation logic, let's handle any validation errors that may occur.
Handling Validation Errors
When a validation error occurs, we want to display an error message and handle it gracefully. Let's modify the Main method of the Program class to handle any exceptions and display meaningful messages to the user.
using System;
using System.Collections.Generic;
public class Program
{
static void Main(string[] args)
{
var pdfService = new PdfService();
// Test 1: Empty Customer Name
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem> {
new InvoiceItem { Description = "Item 1", Price = 19.99M },
new InvoiceItem { Description = "Item 2", Price = 29.99M }
}
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
// Test 2: Empty InvoiceItems
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "John Doe",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem>() // Empty list
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
// Successful generation
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "John Doe",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem> {
new InvoiceItem { Description = "Item 1", Price = 19.99M },
new InvoiceItem { Description = "Item 2", Price = 29.99M }
}
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
}
}
using System;
using System.Collections.Generic;
public class Program
{
static void Main(string[] args)
{
var pdfService = new PdfService();
// Test 1: Empty Customer Name
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem> {
new InvoiceItem { Description = "Item 1", Price = 19.99M },
new InvoiceItem { Description = "Item 2", Price = 29.99M }
}
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
// Test 2: Empty InvoiceItems
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "John Doe",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem>() // Empty list
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
// Successful generation
try
{
var invoiceContent = new InvoiceContent
{
CustomerName = "John Doe",
Address = "123 Main St, Anytown, USA",
InvoiceItems = new List<InvoiceItem> {
new InvoiceItem { Description = "Item 1", Price = 19.99M },
new InvoiceItem { Description = "Item 2", Price = 29.99M }
}
};
var pdfDocument = pdfService.GeneratePdf(invoiceContent);
pdfDocument.SaveAs("C:\\TestInvoice.pdf");
Console.WriteLine("PDF generated successfully!");
}
catch (Exception ex)
{
Console.WriteLine("Error generating PDF: " + ex.Message);
}
}
}
Imports System
Imports System.Collections.Generic
Public Class Program
Shared Sub Main(ByVal args() As String)
Dim pdfService As New PdfService()
' Test 1: Empty Customer Name
Try
Dim invoiceContent As New InvoiceContent With {
.CustomerName = "",
.Address = "123 Main St, Anytown, USA",
.InvoiceItems = New List(Of InvoiceItem) From {
New InvoiceItem With {
.Description = "Item 1",
.Price = 19.99D
},
New InvoiceItem With {
.Description = "Item 2",
.Price = 29.99D
}
}
}
Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
pdfDocument.SaveAs("C:\TestInvoice.pdf")
Console.WriteLine("PDF generated successfully!")
Catch ex As Exception
Console.WriteLine("Error generating PDF: " & ex.Message)
End Try
' Test 2: Empty InvoiceItems
Try
Dim invoiceContent As New InvoiceContent With {
.CustomerName = "John Doe",
.Address = "123 Main St, Anytown, USA",
.InvoiceItems = New List(Of InvoiceItem)()
}
Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
pdfDocument.SaveAs("C:\TestInvoice.pdf")
Console.WriteLine("PDF generated successfully!")
Catch ex As Exception
Console.WriteLine("Error generating PDF: " & ex.Message)
End Try
' Successful generation
Try
Dim invoiceContent As New InvoiceContent With {
.CustomerName = "John Doe",
.Address = "123 Main St, Anytown, USA",
.InvoiceItems = New List(Of InvoiceItem) From {
New InvoiceItem With {
.Description = "Item 1",
.Price = 19.99D
},
New InvoiceItem With {
.Description = "Item 2",
.Price = 29.99D
}
}
}
Dim pdfDocument = pdfService.GeneratePdf(invoiceContent)
pdfDocument.SaveAs("C:\TestInvoice.pdf")
Console.WriteLine("PDF generated successfully!")
Catch ex As Exception
Console.WriteLine("Error generating PDF: " & ex.Message)
End Try
End Sub
End Class
In the code above, try-catch blocks are used to catch any exceptions that may occur. If an exception is caught, an error message will be shown to the user using Console.WriteLine.
Now let's test this application with different scenarios to validate the PDF generation and the validation rules.
Testowanie aplikacji
In the code example, there are three scenarios to test:
- Empty customer name: Leave the customer name empty to trigger a validation error.
- Empty invoice items: Provide an empty list of invoice items to trigger a validation error.
- Successful generation: Provide valid content to generate the PDF successfully.
Run the application and observe the output in the console.
Error generating PDF: Validation failed:
-- CustomerName: Customer name is required. Severity: Error
Error generating PDF: Validation failed:
-- InvoiceItems: At least one invoice item is required. Severity: Error
PDF generated successfully!
The output error in the Console
Plik PDF wynikowy
As expected, validation errors are shown for the first two scenarios and a success message for the third scenario.
Wnioski
This tutorial explored Fluent Validation and how to use it with IronPDF to generate PDF documents. Starting by setting up a Console Application and defining the PDF content class. Then, created validation rules using Fluent Validation and tested the PDF generation with different scenarios.
Fluent Validation provides a flexible and easy-to-use approach for validating objects in .NET applications. It allows you to define validation rules in a strongly typed manner, customize error messages, and handle validation errors gracefully.
IronPDF Free Trial & Licensing Information offers a free trial, and the license starts from $499 per developer.
Często Zadawane Pytania
Jak mogę zintegrować Fluent Validation z generowaniem PDF w C#?
Aby zintegrować Fluent Validation z generowaniem PDF w C#, można skonfigurować aplikację konsolową w Visual Studio, zainstalować pakiety FluentValidation i IronPDF poprzez NuGet oraz zdefiniować logikę walidacji modelu przy użyciu Fluent Validation podczas generowania PDF za pomocą IronPDF.
Jakie kroki są wymagane do skonfigurowania projektu dla generowania i walidacji PDF?
Aby skonfigurować projekt, utwórz nową aplikację konsolową w Visual Studio, zainstaluj pakiety IronPDF i FluentValidation przez NuGet, a następnie zdefiniuj treść PDF i reguły walidacji, używając odpowiednich bibliotek.
Jak mogę wygenerować PDF z treści HTML przy użyciu biblioteki .NET?
Możesz wygenerować PDF z treści HTML, używając metody RenderHtmlAsPdf z IronPDF, która pozwala na konwersję ciągów HTML lub plików do wysokiej jakości PDF.
Jaki jest cel klasy PdfService w tym samouczku?
Klasa PdfService w tym samouczku jest zaprojektowana do zarządzania generowaniem PDF poprzez najpierw walidację treści za pomocą Fluent Validation. Po pomyślnej walidacji używa metod ChromePdfRenderer i RenderHtmlAsPdf z IronPDF do stworzenia PDF.
Jak są definiowane reguły walidacji przy użyciu Fluent Validation?
Reguły walidacji w Fluent Validation są definiowane poprzez tworzenie klasy walidatora, która dziedziczy po AbstractValidator. W tej klasie metoda RuleFor jest używana do określenia warunków dla każdej właściwości, umożliwiając dostosowanie komunikatów o błędach i łączenie reguł.
Co się stanie, jeśli walidacja nie powiedzie się podczas generowania PDF?
Jeśli walidacja się nie powiedzie, Fluent Validation rzuca ValidationException, która zawiera szczegółowe informacje o błędach walidacji, co może być użyte do poinformowania użytkownika, co poszło nie tak.
Czy mogę używać Fluent Validation do walidacji złożonych obiektów?
Tak, Fluent Validation wspiera walidację złożonych obiektów poprzez wykorzystanie walidatorów podrzędnych, umożliwiając walidację zagnieżdżonych właściwości i kolekcji w twoim modelu.
Jak mogę dostosować komunikaty o błędach w Fluent Validation?
Dostosowane komunikaty o błędach w Fluent Validation można zdefiniować przy użyciu metody WithMessage dla każdej reguły walidacji określonej z RuleFor.
Czy jest dostępna wersja próbna dla biblioteki do generowania PDF?
Tak, IronPDF oferuje bezpłatną wersję próbną dla programistów do testowania możliwości biblioteki, z opcjami licencyjnymi zaczynającymi się od 499 USD za dewelopera.
Czy IronPDF jest w pełni kompatybilny z .NET 10?
Tak. IronPDF jest w pełni kompatybilny z .NET 10 i wspiera platformy, w tym Windows, Linux, macOS w różnych typach projektów (konsola, web, desktop, Blazor itp.). Działa bezpośrednio z najnowszym runtime bez potrzeby obejść.




