Lay out known address fields in the order used by their country. Formatting does not check that an address exists or that mail can be delivered there.
dotnet add package RecursiveAI.OneContactRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneContact; var us = PostalAddress.Create(Region.US, adminArea: "IL", locality: "Springfield", postalCode: "62704", streetLines: ["123 Main St"]); var fr = PostalAddress.Create(Region.Parse("FR"), locality: "Paris", postalCode: "75001", streetLines: ["10 rue Exemple"]); foreach (var address in new[] { us, fr }) { Console.WriteLine(address.Country); foreach (var line in address.GetLabelLines()) Console.WriteLine(line); }
US 123 Main St Springfield IL 62704 FR 10 rue Exemple 75001 Paris
Unzip the example, then dotnet run.
Region.US is a convenience property; Region.Parse("FR") reads France’s two-letter country code, since most countries have no named property.
Full program
The full program adds a recipient to both addresses and prints each as a multiline label and a single-line value:
using RecursiveAI.OneContact; var us = PostalAddress.Create(Region.US, adminArea: "IL", locality: "Springfield", postalCode: "62704", recipient: "Ada Example", streetLines: ["123 Main St"]); var fr = PostalAddress.Create(Region.Parse("FR"), locality: "Paris", postalCode: "75001", recipient: "Ada Example", streetLines: ["10 rue Exemple"]); foreach (var address in new[] { us, fr }) { Console.WriteLine(address.Country); foreach (var line in address.GetLabelLines()) Console.WriteLine(line); Console.WriteLine($"Single line: {address.ToSingleLine()}"); }
dotnet run prints:
US Ada Example 123 Main St Springfield IL 62704 Single line: Ada Example, 123 Main St, Springfield IL 62704 FR Ada Example 10 rue Exemple 75001 Paris Single line: Ada Example, 10 rue Exemple, 75001 Paris
Create keeps fields as supplied without validation; call Validate() separately to check their structure.
Variations
Write a French address on one line:
using RecursiveAI.OneContact; var address = PostalAddress.Create(Region.Parse("FR"), locality: "Paris", postalCode: "75001", streetLines: ["10 rue Exemple"]); Console.WriteLine(address.ToSingleLine());
10 rue Exemple, 75001 ParisRelated recipes
- Extract contact information from HTML in C#
- Parse a URL in C#
- Get the domain from a URL in C#
- Parse a postal address in C#
The short answer
Create a PostalAddress from known fields, then call GetLabelLines() for a multiline label or ToSingleLine() for a comma-separated display value. OneContact selects the field order from the address’s country, rather than applying a universal city-state-postcode template.
The snippet at the top shows US and French labels together: the US label places the postal code after the locality and state, while the French label places it before the locality. The full program also includes a recipient and single-line output. Both programs use invented address data; formatting them does not imply that those locations exist. See the structural address layer for the layout rules.
How do I format an address by country in C#?
Pass the country and the fields separately to PostalAddress.Create. Use adminArea for a state, province or equivalent subdivision, locality for the city or town, and streetLines for the street portion. Recipient, organization, dependent locality and sorting code have their own fields where needed.
The formatter follows the selected country’s address format and omits absent fields. Empty street lines are dropped. Multiple street lines remain separate lines in the label, so callers do not need to invent their own separators for apartment or building information. Print or render each returned line in order.
Country is part of the input, not a formatting culture inferred from the computer running the program. A French address should keep its French ordering even if a server’s operating-system culture is English. Set that country deliberately when importing address fields from a form or database.
How do I format an international mailing address?
Use the format data for the destination country. Do not force every address into US fields or add punctuation globally after every value. The format engine knows which fields the country places and which literal separators belong between them. It trims field values and leaves out format text associated with missing values according to its documented layout rules.
Where the data provides both local-script and Latin-script layouts, GetLabelLines can select the appropriate layout through its script option. A country without a Latin-specific format uses its ordinary format. A language tag on the address can also select a documented language variant, such as a French variant for Canada.
This is layout, not translation. The structural layer does not translate a locality name or change the case of supplied field values. If the postal data indicates that a field is conventionally uppercase, that is information exposed by the region metadata; it is not an instruction that the structural formatter silently applies to your strings.
How do I validate an address before formatting it?
Call Validate() separately if your workflow needs structural checks. Create intentionally keeps supplied values without validation, which lets you display an incomplete form while a user is still editing it. Formatting output is therefore not a success signal for validation.
Structural checks can identify missing required fields, fields the country does not use, unknown subdivisions and postal-code format problems. They do not look up individual streets, buildings or mail recipients. An empty issue list means the fields fit the country’s structural rules, not that a postal service will deliver a parcel.
Use free-text parsing only when the input really is a free-text address in a supported country. If fields are already separated, keep them separated and format directly. This preserves the information you collected and avoids trying to guess the boundaries a second time.