Architecture

This help article describes the structure and architecture of the typical Radzen application.

Layers

Radzen applications have two layers:

  • Angular or Blazor application

This is a client-side SPA (single-page application) that runs in the browser of your users. It supports responsive web design out of the box which makes it fit various device sizes - desktop, tablet and mobile.

  • .NET Core application

This is an optional server-side .NET Core application that exposes your MS SQL, MySQL or PostgreSQL databases as OData services. OData is an open protocol that serves data in JSON format over RESTful API.

The .NET Core application also handles application security (authentication and authorization).

Folders

The Radzen applications has three top-level directories:

client
meta
server

The client directory contains the client-side (Angular or Blazor) application.

The meta directory contains JSON files that describe the application structure - data sources, pages, assets. Radzen generates the contents of the client and server directories from those files.

The server directory contains the server-side (.NET Core) application.

Angular application

The Radzen Angular application (output in the client directory) follows the Angular CLI guidelines:

client
src
app
<page-name>
<page-name>.component.html
<page-name>.component.ts
<page-name>.component.ts
<data-source>.model.ts
<data-source>.service.ts

Every Radzen page outpus three files in their own directory:

  1. <page-name>.component.html - the template of the page which contains the HTML markup of the UI components. This file is generated always. Any changes made to it by the user will be overwritten.
  2. <page-name>-generated.component.ts - TypeScript class that implements the Angular component - handles UI component events (e.g. button clicks), loads data from a RESTful API etc. This file is generated always. Any changes made to it by the user will be overwritten.
  3. <page-name>.component.ts - TypeScript class that inherits from the one defined in <page-name>-generated.component.ts. Its purpose is to allow extensibility via custom code.

Check customizing the application code for more details.

Angular Components

Radzen relies on the powerful PrimeNG component library. Charts are powered by D3 via the ngx-charts library.

Radzen users can also add custom Angular components or wrap 3rd party ones.

Blazor application

The Radzen Blazor application (output in the client directory) follows the default .NET Core CLI Blazor template guidelines.

Blazor is still experimental and so is the current Radzen support. Feature parity with Radzen Angular applications will be reached once Microsoft releases Blazor officially in .NET Core 3.0 (Q1 2019).

Every Radzen page outpus two files in their own directory:

  1. <page-name>.cshtml - the template of the page which contains the HTML markup of the UI components. This file is generated always. Any changes made to it by the user will be overwritten.
  2. <page-name>.cshtml.cs - C# class that implements the Blazor component - handles UI component events (e.g. button clicks), loads data, etc. This file is generated always. Any changes made to it by the user will be overwritten.

Blazor applications FAQ

Here is a quick FAQ regarding Blazor support in Radzen:

Does Radzen support client-side or server-side Blazor?

Radzen currently supports server-side Blazor (a.k.a. Razor components) because Microsoft will release it first.

Can I migrate my existing Radzen Angular application to Blazor?

Not yet. Your current Radzen application is probably relying on features that are not available yet.

What UI components are you using in Radzen Blazor applications?

We are developing a brand new suite of native Blazor components. Native means that we don’t wrap existing JS libraries - everything is 100% Blazor code compatible with Blazor data-binding, templates and event handling.

When will component X be available in Radzen Blazor applications?

We will gradually implement the remaining components from the Radzen toolbox.

.NET Core Application

A server-side application is needed to support the following Radzen features:

  • Database access (MSSQL, MySQL or Postgres)
  • Security (ActiveDirectory or built-in)
  • Export to Excel (CSV or XSLX format)

Data-access is achieved by using Entity Framework Core. The database tables are exposed as OData entities available in debug mode at the following URL: http://localhost:5000/odata/<data-source>/<entity> e.g. http://localhost:5000/odata/Northwind/Customers.

Every table (or database view) has a corresponding ODataController with CRUD operations generated out of the box. Here is an example:

[ODataRoutePrefix("odata/Northwind/Customers")]
public partial class CustomersController : ODataController
{
  private NorthwindContext context;

  public CustomersController(NorthwindContext context)
  {
    this.context = context;
  }

  // GET /odata/Northwind/Customers
  [EnableQuery(MaxExpansionDepth=10)]
  [HttpGet]
  public IEnumerable<Models.Northwind.Customer> GetCustomers()
  {
    var items = this.context.Customers.AsQueryable<Models.Northwind.Customer>();

    this.OnCustomersRead(ref items);

    return items;
  }

  partial void OnCustomersRead(ref IQueryable<Models.Northwind.Customer> items);

  [EnableQuery(MaxExpansionDepth=10)]
  [HttpGet("{CustomerID}")]
  public SingleResult<Customer> GetCustomer(string key)
  {
      var items = this.context.Customers.Where(i=>i.CustomerID == key);

      return SingleResult.Create(items);
  }

  partial void OnCustomerDeleted(Models.Northwind.Customer item);

  [HttpDelete("{CustomerID}")]
  public IActionResult DeleteCustomer(string key)
  {
      var item = this.context.Customers
          .Where(i => i.CustomerID == key)
          .Include(i => i.Orders)
          .Include(i => i.CustomerCustomerDemos)
          .SingleOrDefault();

      if (item == null)
      {
          return NotFound();
      }

      this.OnCustomerDeleted(item);
      this.context.Customers.Remove(item);
      this.context.SaveChanges();

      return new NoContentResult();
  }

  partial void OnCustomerUpdated(Models.Northwind.Customer item);

  [HttpPut("{CustomerID}")]
  public IActionResult PutCustomer(string key, [FromBody]Models.Northwind.Customer newItem)
  {
      if (newItem == null || (newItem.CustomerID != key))
      {
          return BadRequest();
      }

      this.OnCustomerUpdated(newItem);
      this.context.Customers.Update(newItem);
      this.context.SaveChanges();

      return new NoContentResult();
  }

  [HttpPatch("{CustomerID}")]
  public IActionResult PatchCustomer(string key, [FromBody]Delta<Models.Northwind.Customer> patch)
  {
      var item = this.context.Customers.Where(i=>i.CustomerID == key).FirstOrDefault();

      if (item == null)
      {
          return BadRequest();
      }

      patch.Patch(item);

      this.OnCustomerUpdated(item);
      this.context.Customers.Update(item);
      this.context.SaveChanges();

      return new NoContentResult();
  }

  partial void OnCustomerCreated(Models.Northwind.Customer item);

  [HttpPost]
  public IActionResult Post([FromBody] Models.Northwind.Customer item)
  {
      if (item == null)
      {
          return BadRequest();
      }

      this.OnCustomerCreated(item);
      this.context.Customers.Add(item);
      this.context.SaveChanges();

      return Created($"odata/Northwind/Customers/{item.CustomerID}", item);
  }
}

Radzen outputs the server-side application in the server directory in the following structure:

server
Startup.cs
Data
Models
<data-source>
<table>.cs
Controllers
<data-source>
<table>Controller.cs
  • Startup.cs contains initialization and configuration code. The class is partial to allow for further customization via partial methods.
  • The Data directory contains the Entity Framework Core DBContext classes that Radzen has generated for every data source.
  • The Models directory contains a sub-directory for every data source and then a class for every table e.g. Models\Northwind\Customer.cs - the model (class with properties) that corresponds to the Customers table from Northwind database.
  • The Controllers directory contains a sub-directory for every data source and then an OData controller for every table e.g. Controllers\Norhtwind\CustomersController.cs - the controller (with implemented CRUD operations) that exposes the Customers table from the Northwind database as an OData entity.

Most of the generated classes are partial to allow for customization via partial methods. More info is available in the customization help article.

We are here for you

Making our users happy is always a priority for us.