Skip to content

Global Configurations

Alexandr Makarov edited this page Jan 29, 2025 · 5 revisions

Contents

Customizing the Endpoint

By default, NetForge Admin is running on /admin but you can configure to use your custom endpoint like this:

appBuilder.Services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.UseEndpoint("/manage");
    ...
});

Customizing the Title

You can customize the header title like this:

appBuilder.Services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetHeaderTitle("title");
    ...
});

And customize the HTML title like this:

appBuilder.Services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetHtmlTitle("title");
    ...
});

Configuring Authorization

You can customize the access policy by requiring specific Identity roles:

appBuilder.Services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.AddAccessRoles("Role1", "Role2", "Role3");
    ...
});

Alternatively, you can use a custom function to perform authorization checks. Example:

appBuilder.Services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.ConfigureAuth(serviceProvider =>
    {
        // Allow all authenticated users to see the Admin Panel.
        var httpContext = serviceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
        return Task.FromResult(httpContext?.User.Identity?.IsAuthenticated ?? false);
    });
});

Search

You can read about search here.

View Site URL

Located in the top right corner of the admin panel is a "View Site" link, configurable to direct users to the website URL. The default URL is "/". You can customize this value using the Fluent API:

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.ConfigureUrl("https://www.example.com/");
});

Grouping

Group rows of entities into categories and make it easier for users to navigate and understand the data presented.

Customizing the UI

Main Layout Overriding

You can override the default layout of the admin panel. To do this, create a new layout in your host project and specify its type in the configuration.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetCustomLayout(typeof(CustomLayout));
});

Your custom layout should inherit from the AdminBaseLayout class.

The example of the custom component with navigation bar and footer:

@using MudBlazor
@inherits Saritasa.NetForge.Blazor.Shared.AdminBaseLayout

<MudThemeProvider />
<MudDialogProvider />
<MudSnackbarProvider />

<MudAppBar Color="Color.Primary" Elevation="4">
    <MudText Typo="Typo.h6">My Application</MudText>
    <MudSpacer />
    <MudNavMenu>
        <MudNavLink Href="/about">About</MudNavLink>
        <MudNavLink Href="/contact">Contact</MudNavLink>
    </MudNavMenu>
</MudAppBar>

@Body

<footer>
    <MudPaper Class="pa-4" Elevation="4">
        <MudText Typo="Typo.body2">My Application</MudText>
        <MudSpacer />
        <MudNavMenu>
            <MudNavLink Href="/privacy">Privacy Policy</MudNavLink>
            <MudNavLink Href="/terms">Terms of Service</MudNavLink>
        </MudNavMenu>
    </MudPaper>
</footer>

Head Tag Overriding

You can inject custom meta tags or page title into the head tag of the admin panel.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetCustomHeadType(typeof(CustomHead));
});

Example of injecting custom meta tags or a page title into the head tag of the admin panel.

@using Microsoft.AspNetCore.Components.Web

<PageTitle>This is the custom page title.</PageTitle>
<meta name="custom-meta" content="content-meta">

Note: If you are using a Custom Layout, you must add the dynamic component into the custom layout:

@using Saritasa.NetForge.Domain.Entities.Options
@inject AdminOptions AdminOptions;

<HeadContent>
    @if (AdminOptions.CustomHeadType is not null)
    {
        <DynamicComponent Type="AdminOptions.CustomHeadType" />
    }
</HeadContent>

Example:

@using MudBlazor
@using Saritasa.NetForge.Domain.Entities.Options
@using Microsoft.AspNetCore.Components.Web
@inherits Saritasa.NetForge.Blazor.Shared.AdminBaseLayout
@inject AdminOptions AdminOptions;

<HeadContent>
    @if (AdminOptions.CustomHeadType is not null)
    {
        <DynamicComponent Type="AdminOptions.CustomHeadType" />
    }
</HeadContent>

<MudThemeProvider />
<MudDialogProvider />
...
...

Custom Body Content

You can add some content to the end of the body section of admin site. Static and interactive content can be added separately.

Static Content

Static content will be rendered by your custom component type.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetStaticBodyComponentType(typeof(AdminFooterStatic));
});

Interactive Content

Interactive content can be built using RenderTreeBuilder. Note that JavaScript script tags should not be here. If you need JavaScript then put it to the static content section. But you can import JavaScript file in your component to use it, in this case you will not need script tag. Like in JsCollocation2 example here.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetInteractiveBodyContent(builder =>
        {
            builder.OpenComponent<AdminFooter>(0);
            builder.AddAttribute(1, nameof(AdminFooter.VisitorsCount), 1234);
            builder.CloseComponent();
        })
});

Using CSS

To use CSS in custom body sections you should add it to Custom Head Section. Also, you can use scoped CSS, in this case you should add bundled styles according to this. For example:

<link href="Saritasa.NetForge.Demo.styles.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">

Create Groups for Entities

Before assigning entities to specific groups, users need to define the groups to which the entities will belong. To create a new group, utilize the Fluent API through AdminOptionsBuilder. A name is required for each group, and a description is optional.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.UseEntityFramework(efOptionsBuilder =>
    {
        efOptionsBuilder.UseDbContext<ShopDbContext>();
    }).AddGroups(new List<EntityGroup>
    {
        new EntityGroup{ Name = "Product", Description = "Contains all information related to products" },
        new EntityGroup{ Name = "Shop"}
    }).ConfigureEntity<Shop>(entityOptionsBuilder =>
    {
        entityOptionsBuilder.SetDescription("The base Shop entity.");
    });
});

Configuration

By default, entities are assigned to the "empty" group. Grouping can be customized either through the Fluent API or by using attributes. When assigning entities to a group, users only need to specify the group's name. If user specifies a group that does not exists for an entity, that entity will belong to the default group.

Fluent API:

By utilizing EntityOptionsBuilder, user can set group for entity using group's name.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.UseEntityFramework(efOptionsBuilder =>
    {
        efOptionsBuilder.UseDbContext<ShopDbContext>();
    }).AddGroups(new List<EntityGroup>
    {
        new EntityGroup{ Name = "Product", Description = "Contains all information related to products" },
        new EntityGroup{ Name = "Shop"}
    }).ConfigureEntity<Shop>(entityOptionsBuilder =>
    {
        entityOptionsBuilder.SetGroup("Shop");
        entityOptionsBuilder.SetDescription("The base Shop entity.");
    });
});

Data Attribute:

[NetForgeEntity(GroupName = "Product")]
public class ProductTag

Headers Expansion

You can customize expanded header of all groups. By default, all groups are expanded.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetGroupHeadersExpanded(true);
});

Success Messages

You can customize success messages on operations with entities. It can be customized on Global and Per-Model levels. Per-Model takes precedence on Global level.

Create

Global Level
services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetEntityCreateMessage("The entity was created.");
});
Per-Model Level
  public void Configure(EntityOptionsBuilder<Address> entityOptionsBuilder)
  {
      entityOptionsBuilder.SetEntityCreateMessage("Address was created.");
  }

Save

Global Level
services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetEntitySaveMessage("Entity was saved.");
});
Per-Model Level
  public void Configure(EntityOptionsBuilder<Address> entityOptionsBuilder)
  {
      entityOptionsBuilder.SetEntitySaveMessage("Address was saved.");
  }

Delete

Global Level
services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetEntityDeleteMessage("The entity was deleted.");
});
Per-Model Level
  public void Configure(EntityOptionsBuilder<Address> entityOptionsBuilder)
  {
      entityOptionsBuilder.SetEntityDeleteMessage("Address was deleted.");
  }

Bulk Delete

Global Level
services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetEntityBulkDeleteMessage("The entities were deleted.");
});
Per-Model Level
  public void Configure(EntityOptionsBuilder<Address> entityOptionsBuilder)
  {
      entityOptionsBuilder.SetEntityBulkDeleteMessage("Selected addresses were deleted.");
  }

Exclude All Entities and Include Specific Only

You can exclude all entities and include only specific ones.

services.AddNetForge(optionsBuilder =>
{
    optionsBuilder.SetIncludeAllEntities(false);
    optionsBuilder.IncludeEntities(typeof(Shop), typeof(Product));
});

Or you can include specific entities using the data attribute:

[NetForgeEntity]
public class Shop