{"id":21937853,"url":"https://github.com/apps72/blazorguidelines","last_synced_at":"2025-08-06T11:17:41.350Z","repository":{"id":47013869,"uuid":"407206541","full_name":"Apps72/BlazorGuidelines","owner":"Apps72","description":"A set of coding guidelines for Microsoft Blazor projects, design principles and layout rules for improving the overall quality of your code development.","archived":false,"fork":false,"pushed_at":"2023-01-09T10:15:53.000Z","size":29,"stargazers_count":19,"open_issues_count":6,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-22T12:28:11.189Z","etag":null,"topics":["blazor","community","guidelines","hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Apps72.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-16T14:56:04.000Z","updated_at":"2025-01-05T22:37:43.000Z","dependencies_parsed_at":"2023-02-08T09:45:14.564Z","dependency_job_id":null,"html_url":"https://github.com/Apps72/BlazorGuidelines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Apps72/BlazorGuidelines","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Apps72%2FBlazorGuidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Apps72%2FBlazorGuidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Apps72%2FBlazorGuidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Apps72%2FBlazorGuidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Apps72","download_url":"https://codeload.github.com/Apps72/BlazorGuidelines/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Apps72%2FBlazorGuidelines/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269068023,"owners_count":24354403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-06T02:00:09.910Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blazor","community","guidelines","hacktoberfest"],"created_at":"2024-11-29T01:26:10.910Z","updated_at":"2025-08-06T11:17:40.410Z","avatar_url":"https://github.com/Apps72.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📄 Blazor Guidelines 📄\n\nA set of coding guidelines for Microsoft Blazor projects, design principles and layout rules for improving the overall quality of your code development.\n\nThis part of the document is mainly based...\n\n1.\tOn our experience to write the simplest and best performing code possible.\n2.\tOn [how to create and use Razor components in Blazor apps](https://docs.microsoft.com/en-us/aspnet/core/blazor/components) documentation.\n3.\tOn [Microsoft Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions).\n\n## 🔸Component Name\n\n- Component file paths use **Pascal Case**. Paths indicate typical folder locations. For example, `Pages/ProductDetailPage.razor` indicates that the `ProductDetailPage` component has a file name of `ProductDetailPage.razor` and resides in the `Pages` folder of the app.\n\n- Component file paths for routable components match their URLs with hyphens appearing for spaces between words in a component's route template. For example, a `ProductDetailPage` component with a route template of `@page \"/product-detail\"` is requested in a browser at the relative URL `/product-detail`.\n\n- A component's name uses Pascal case. For example, `ProductDetailPage.razor` is valid.\n\n## 🔸Component Structure\n\nOrganize files and components in a folder structure like this. This makes it easy to find the code related to a page, without having to browse the entire file explorer. Try, as much as possible, to respect the [SOLID](https://en.wikipedia.org/wiki/SOLID) principles. Mainly by creating autonomous and extensible components: inject the smallest possible service or parameter, manage all the possibilities offered by the component. For example, a data modification page should display the data, check their values and save the data at the end of the process.\n\n- Group pages and dialog boxes of the **same module** in a sub-folder of **Pages** folder, with this module name (pluralized). For example: `Pages\\Assets\\`.\n- Suffix pages with **Page.razor** and dialog boxes with **Dialog.razor**. Name the page name in the singular. For example: `\\Pages\\Assets\\AssetMainPage.razor` and `\\Pages\\Assets\\AssetEditDialog.razor`.\n- Put the **parameters** of a dialog box in a class `[Name]DialogParameters`.\nAnd save it into the file `[Name]Dialog.razor.Parameters.cs`, to use the \"**Nested files**\" representation in Visual Studio. See the example `AssetCloneDialog.razor.Parameters.cs` below.\n- The code behind a dialog box (for example, to save data) must be in this class. For example, in the **OnCloseAsync** method (or equivalent method) of this class. Don’t write logic dialog box features in the main call window (except to refresh the main screen).\n- Common and project shared components (between multiple modules) are stored in a folder **Components**, and are suffixed by `Component`.\n\nFor example:\n```\n|-- App.razor\n|-- Components\n|   |-- TimeComponent.razor\n|   |-- TimeComponent.razor.cs\n|-- Pages\n|   |-- Calendars\n|   |   |-- CalendarMainPage.razor\n|   |   |-- CalendarMainPage.razor.cs\n|   |   |-- CalendarMainPage.razor.css\n|   |   |-- CalendarMainPage.razor.js\n|   |   |-- CalendarEditDialog.razor\n|   |   |-- CalendarEditDialog.razor.cs\n|   |   |-- CalendarEditDialog.razor\n|   |   |-- CalendarEditDialog.razor.Parameters.cs\n```\n\nVSCode and Visual Studio have a File nesting feature to regroup visually each item of same page or dialog. In VSCode, set this settings: `\"explorer.fileNesting.patterns\": { \"$(capture).razor, $(capture).razor.*\"`.\n\n\n## 🔸C# code in the .razor.cs\n\nFrom our experience, we have chosen not to use the ```@code``` element in files with the ```.razor``` extension. \nC# code should be in the ```.razor.cs``` file provided for this purpose.\n\nDiscussion via issue Discussion via [issue #2](https://github.com/Apps72/BlazorGuidelines/issues/2)\n\n## 🔸Add injection via Code Behind\n\nThe .razor is only used for the design part and the layout of this HTML design (via loops and Razor tests).\nPut all the code in the \"Code Behind\" file, including properties injected (using private accessor). \nAll attributes are above of the property/method.\n\n```csharp\n[Inject]\nprivate IMemoryCache MemoryCache { get; set; }\n```\n\nDiscussion via issue Discussion via [issue #1](https://github.com/Apps72/BlazorGuidelines/issues/1)\n\n## 🔸Send HTML as soon as possible\n\nFor example, if you have a component that is linked to a sub-property, **it is better to set default values for all linked properties**, instead of testing the initial variable. \n\n```razor\n// DON'T USE\n@if (MyData != null)\n{\n    \u003cinput type=\"text\" value=\"MyData.Firstname\"\u003e\n}\n```\n\n```razor\n// PREFERS\n\u003cinput type=\"text\" value=\"MyData.Firstname\"\u003e\n\n@code \n{\n     MyData MyData { get; set; } = new MyData();\n}\n```\n\nThis allows Blazor to send the HTML code to the client who can display it. \nThen Blazor, via SignalR, will update the content of the component that is already drawn.\nOtherwise, an empty page is displayed to the user, while the whole component is known... \nwhich is not ergonomically pleasant for the user.\n\nTh easy way to do that, is to bind to empty objects... including all sub properties must be defined.\n\nDiscussion via [issue #11](https://github.com/Apps72/BlazorGuidelines/issues/11)\n\n## 🔸Abuse of CSS isolation\n\nIt is preferable to use as much as possible a css / .razor.\n\n```\nMyPage.razor\n  \\-- MyPage.razor.cs\n  \\-- MyPage.razor.css\n```\n\nDiscussion via [issue #4](https://github.com/Apps72/BlazorGuidelines/issues/4)\n\n## 🔸JavaScript collocated with a component\n\n[Collocation of JavaScript files](https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/?view=aspnetcore-6.0#load-a-script-from-an-external-javascript-file-js-collocated-with-a-component) for pages and Razor components is a convenient way to organize scripts in an app: it's easier to centralize and find the JS code associated to a component. It does not pollute the client with global functions. And the component will load this code only when needed.\nSave the JavaScript code in a .js file below the component.\n\n1.\tCreate a `[Component].razor.js` file with your JavaScript code.\n\n```javascript\nexport function myModule_myJsMethod() {\n    ...\n}\n```\n\n2.\tAdd the following constant and two properties.\n\n```csharp\nprivate const string JAVASCRIPT_FILE = \"./Pages/[Path]/[Component].razor.js\";\n\t\t  \n[Inject]\nprivate IJSRuntime JsRuntime { get; set; } = default!;\n\nprivate IJSObjectReference JsModule { get; set; } = default!;\n```\n\n3.\tCall the JavaScript function, from your C# code, as follows.\n\n```csharp\nif (JsModule == null)\n{\n  JsModule = await JsRuntime.InvokeAsync\u003cIJSObjectReference\u003e(\"import\", JAVASCRIPT_FILE);\n}\nawait JsModule.InvokeVoidAsync(\"myModule_myJsMethod\");\n```\n\n## 🔸Methods and properties\n\nThe variables and properties must be organized in the following order.\n\n1.\tPrivate **variables** (using readonly if possible) and constants\n2.\tThe **[Inject]** properties\n3.\t**[Parameter]** properties\n4.\t**Public** methods and properties\n5.\t**Internal** and **Protected** methods/properties\n6.\t**Private** methods/properties\n\nPlace the **attributes** (Inject, Parameter, …) above the property.\n```csharp\n[Inject]\npublic IJSRuntime JsRuntime { get; set; } = default!;\n```\n\nSince the project has been defined as accepting nullables, it is recommended to define non-null variables and properties with a `default!` value. To avoid having a warning, at compile time, assign this value by default, only to properties that do not accept null values. For properties that accept null values, don't forget to define them with the `?` (including simple types or objects like `string?`, `int?` or `object?`.\n```csharp\npublic IConnectionManager Connection { get; set; } = default!;\n```\n\n\n\n\n# ❔How it works and how to contribute?\n\n## 🔹This project is discussion based\n\nIn order to put values on this guidelines, you need to create an issue and a context to allow understand your lines. \n\nWhen it's validated by the community, you can then create a pull request to add values on this project.\n\n## 🔹Owners\n\nThis project is owned by : \n\n* Adrien Clerbois @AClerbois\n* Denis Voituron @Dvoituron\n* Christophe Peugnet @Tossnet\n\n## 🔹Code of Conduct\nThis project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information, see the [Code of Conduct.](https://github.com/Apps72/BlazorGuidelines/blob/main/CODE_OF_CONDUCT.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapps72%2Fblazorguidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapps72%2Fblazorguidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapps72%2Fblazorguidelines/lists"}