Razor Standards

Razor pages allow multiple languages to be used within the same file. It’s important to apply standards to keep things consistent and make navigation and readability as easy as possible.

This article is broken up into multiple sections of what makes up a razor component by the language with standards specific to that area.

CSS (Styling)

Declare ALL CSS classes within a <style> tag at the top of the component.

Why? – Keeps layout of all components the same to improve navigation.


If the styles defined in a class are also in another component, then refactor the components and move the CSS class declaration and styles into the app.css file instead.

Why? – Improves maintainability since the class and styles are defined in one place instead of multiple.


Inline CSS on HTML elements is allowed but should be refactored into a class if the styles are defined on more than one element.

Why? – Improves maintainability since a modification to the styles only needs to be updated in one place.


Classes with styles that adjust colors should be moved out of the component and into the app.css file instead.

Why? – Each theme has its own color scheme, so keeping color specific styles in the individual themes app.css file allows colors to display based on the themes color scheme. If the style is in the component, then it will be applied on all themes.


Use classes provided by the Telerik theme where possible (Classes prefixed with “k-“).

Why? – Provides consistency, and the styling will stay consistent across each theme.


IMPORTANT NOTE: If you’re putting styles into the app.css file ensure that you also update the app.css files for all other supported themes!

HTML (Markup)

Declare HTML at the top of the component or below the <style> tag if you’re using styles.

Why? – Keeps the layout of components consistent to improve navigation and readability.


Utilize Telerik components as often as possible.

Why? – Drives consistency across the components in terms of usability and styling.


Add TabIndex = 0 and AriaLabels for accessibility on components that has user interaction. (TabIndex and AriaLabel properties on Telerik components)

Why? – Improves keyboard navigation and accessibility for screen readers.


Avoid using @if statements where possible in the markup.

Why? – In some cases, having an @if will cause the component to be loaded twice. This is undesirable and may degrade performance, especially if the component makes API calls or takes a while to load.

JavaScript

Don’t use any JavaScript in the components, instead use JsInterop and have all your JavaScript code in a dedicated location (e.g., the helper.js file).

Why? – It’s best practice to use JavaScript this way in Blazor and keeps components code clean.

C# (@code)

Declare the @code section that the bottom of the component below the CSS and HTML.

Why? – Keeps the layout of components consistent, also improves navigation and readability.


Structure the @code section like so from top to bottom:

  • Parameters
  • Variables
  • Methods

Why? – Provides consistency across components to improve navigation.


Declare all parameters, variables, and method names using PascalCase.

Why? – Follows our C# standards.


Variables should only be declared at the member level if they’re used in at least one of the following scenarios. If the variable is only used within one method then it should be declared as a local variable to that method.

  • Referenced in the HTML and a method.
  • Referenced in two or more methods.

Why? – Consistent with our C# standards and improves readability.


Any classes that are defined within the @code region and are only used by that one component should be labeled as sealed.

Why? – Improves performance.

// Don't do this.
public class Address
{
    public int StreetNumber = 0;
    public string StreetName = "";
    public string City = "";
    public string PostCode = "";
    public string State = "";
    public string Country = "";
}

// Do this.
public sealed class Address
{
    public int StreetNumber = 0;
    public string StreetName = "";
    public string City = "";
    public string PostCode = "";
    public string State = "";
    public string Country = "";
}

When creating custom objects that will be used with Telerik components ensure to use getters and setters for their properties.

Why? – Often will prevent the component from working as intended, for example, data not being displayed.

// Don't do this.
public sealed class MenuItem
{
    public string Name = "";
    public string Position "";
    public List<MenuItem> SubItems = new();
}

// Do this.
public sealed class MenuItem
{
    public string Name { get; set; }
    public string Position { get; set; }
    public List<MenuItem> SubItems { get; set; }
}

Declare all async methods as Tasks.

Why? – Avoids confusion between sync methods since method calls need to be awaited.

Don't do this.
private async void ValueChanged()
{
    //...
}

// Do this.
private async Task ValueChanged()
{
    //...
}

Keep the order of methods in the logical order they’re called.

Why? – Keeps components consistent and easier to navigate.


Declare all methods that are OnClick handlers as async.

Why? – So you can catch and log any potential exceptions, if the exception is uncaught then it will propagate to the HTML can crash the application.


Always display the notification before logging exceptions, not after.

Why? – Gives the user instant visual feedback that something went wrong so they’re not stuck waiting. If the user is on a slow network connection logging the exception first could take a while.


Add regions if the @code section is becoming very large.

Why? – Helps group similar methods together to keep things organized. This helps improve navigation and the regions can be referenced in documentation to make the documentation easier to follow.


IMPORTANT NOTE: The @code section is comprised of C# code, so in addition to the standards in this section, all the standards in the C# Standards article should also be applied.

Sample Component

Below is an example of a typical razor component that is used as a field component.

@*Custom field styles would go here.*@

@*Markup for the component would go here.*@

@code {
    [Parameter]
    public XElement FieldUX { get; set; }
    [Parameter]
    public XElement FieldDefinition { get; set; }
    [Parameter]
    public FormBuilder MyInstance { get; set; }
    [CascadingParameter]
    protected Notification Notification { get; set; }

    // Component variables...

   protected override async Task OnParametersSetAsync()
   {
       try
        {
            // Your code goes here...

            await base.OnParametersSetAsync();
        }
        catch (Exception ex)
        {
            Notification.ShowDefaultErrorNotification("Failed to load field!");
            await EventLog.Log(1, "ComponentName.OnParametersSetAsync - Unknown", ex.ToString());
        }
   }
}

The important piece of this sample is the @code block. First are the component parameters, this is the default parameter list for field components. Next is the OnParametersSetAsync method, this is the preferred method to be used to perform all initial tasks for the component such as assigning variable values, especially if this is a field component.

The alternative to the OnParametersSetAsync is the OnInitializedAsync method. The difference between the two is OnInitializedAsync is only called when the component is first initialized then never again, OnParametersSetAsync on the other hand is called after OnInitializedAsync and any time there’s an update to the parent component.

This is important to understand to avoid having an issue where a component is re-rendered but is now using the wrong data. For example, you have a Childlist field on tab A that displays a list of customers, you also have a Childlist field on tab B that displays a list of invoices. If you’re on tab A then switch to tab B you will see customers listed in the invoices Childlist if the childlist component used the OnInitializedAsync method. If you use the OnParametersSetAsync method then it will be called when the tab changes (parent component updates) and you can properly handle what to do such as reassigning variable values and refreshing the childlist.

OnInitializedAsync is only safe to use if you can guarantee that the component won’t need to be re-rendered from an update from a parent component. For more detailed information regarding Blazor and component methods and their workflow, visit Blazor Universities Component Lifecycles article.

Updated on January 11, 2024

Was this article helpful?

Related Articles

Need Support?
Can’t find the answer you’re looking for? Don’t worry we’re here to help!
Contact Support

Leave a Comment