Open Closed

Non nullable types in Angular proxy generation #10762


User avatar
0
LW created

Hello, We upgraded our application from 9.3.7 to 10.3.0. Why is the proxy generation generating nullable properties for Dto properties that are of basic type such as "int, boolean, etc." I would hate to add required attribute for all the properties that are already defined as non nullable in the Dto.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

5 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • Starting with ABP v10.x, the Angular proxy generator marks a DTO property as optional (adds ?) when that property is not required in the backend API contract (OpenAPI/Swagger schema). This is why you now see quantity?: number; even if the C# property type is a non-nullable value type like int, bool, etc.
    • In practice, ABP’s API definition/OpenAPI metadata does not automatically treat every non-nullable value type as “required”. If a property is not explicitly marked “required” in the schema, the TypeScript generator correctly models it as optional to reflect that the server may omit it.

    What to do if you want quantity: number (non-optional) in generated proxies

    1. Make the property required in the contract by adding validation attributes (this is the intended way because it affects the API schema):
    using System.ComponentModel.DataAnnotations;
    
       public class QuantityByDateDto
       {
           [Required]
           public int Quantity { get; set; }
    
           [Required]
           public DateTime Date { get; set; }
       }
    

    This will cause the OpenAPI schema to mark these fields as required, and the Angular proxy generator will generate them without ?.

    1. If the DTO is used only as output and you don’t want to decorate everything with [Required], then there is no verified ABP-side switch (in v10.3 docs/context) to “force non-nullable value types to be required” in Angular generation. The generator follows the API schema.

    Sources (validated):

    • https://docs.abp.io/en/abp/latest/UI/Angular/Service-Proxies
    • https://abp.io/docs/10.3/cli/

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    LW created

    Why was this change introduced?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Starting with v10, the Angular proxy generator treats two things separately for each property:

    • whether it's optional (?) — decided only by whether the property is required in the API contract, i.e. it has a [Required] attribute or the C# required modifier
    • whether it's nullable (| null) — decided by whether the C# type itself is nullable

    So a plain int/bool without [Required] now comes out as quantity?: number, simply because nothing in the contract marks it as required. It's no longer tied to it being a non-nullable value type, and the same ? rule now applies uniformly to int, bool, string, enum, Guid, etc. Note this is just a TypeScript optional (?), not number | null — you only get | null when the C# type itself is nullable.

    This came from this issue: https://github.com/abpframework/abp/issues/24306 (changed in https://github.com/abpframework/abp/pull/24335). The old logic was inconsistent — value types, reference types, strings and enums each followed a different rule for the ?, so the same "not required" property could be optional or not depending only on its type. The new behavior keeps isRequired and isNullable as two independent flags in the API definition, the same way OpenAPI separates required from the type/nullability of a property.

    If a property is always present in your responses and you want it back as quantity: number, mark it as required:

    public class QuantityByDateDto
    {
        [Required]
        public int Quantity { get; set; }
    
        [Required]
        public DateTime Date { get; set; }
    }
    

    [Required] is the cleanest way to do this. The C# required modifier produces the same result, but since it's a language-level constraint it can force you to update existing object initializers / mapping code, so for plain DTOs [Required] is usually less intrusive.

    A couple of things worth keeping in mind: there's no global switch to make every non-nullable value type required — it's per property. And this only changes the generated TypeScript contract; the backend still serializes the same JSON as before, so it's not that the server suddenly omits the field. Marking the always-present fields as required also makes your API contract more accurate for any client, not just the TypeScript side.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    LW created

    Ok, thanks! So, if I understood correctly, we could mark all the properties as required now? Our only api client is the Angular client and there we have used only typed objects to call the api (through the proxies), thus every property should have previously been set.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Yes, that works — marking a property [Required] makes the proxy generate it without the ?.

    It helps to know how it behaves on the server before applying it broadly:

    • On value types (int, bool, DateTime, Guid) [Required] is effectively a no-op. A non-nullable value type is never "missing" as far as validation is concerned, so it never triggers a required error — the only visible effect is the non-optional proxy.
    • On reference types it depends on nullable reference types. If your project has NRT enabled (the default in current ABP templates), a non-nullable string is already treated as required by ASP.NET Core model validation, even without the attribute — so adding [Required] there mostly just lines the proxy up with what the server already does. It's the nullable ones (string?) where [Required] adds a genuinely new server-side rule.

    The reference-type behavior is documented here: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-10.0#non-nullable-reference-types-and-required-attribute

    So in your case (Angular-only, typed proxies, values always set) marking the genuinely-required properties is safe. I'd just avoid blanket-adding it to filter/search or partial-update DTOs where some fields are meant to stay optional. There's no global switch, so it stays per property.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 16, 2026, 14:50
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.