Skip to main content
This guide will walk you through creating your first UI Metadata Framework form. You’ll build a simple calculator that adds two numbers, and see how UIMF automatically generates metadata for your frontend.

Prerequisites

Before you begin, make sure you have:
  • .NET Standard 2.0 or .NET Framework 4.7.2+ installed
  • A C# project (console app, web API, etc.)
  • Basic familiarity with C# and attributes

Step 1: Install the NuGet packages

1

Install UiMetadataFramework.Core

This package provides the core framework functionality:
dotnet add package UiMetadataFramework.Core
2

Install UiMetadataFramework.Basic

This package provides basic input/output components:
dotnet add package UiMetadataFramework.Basic

Step 2: Create your first form

Let’s create a simple form that adds two numbers. Create a new C# file called AddNumbers.cs:
AddNumbers.cs
using UiMetadataFramework.Basic.Server;
using UiMetadataFramework.Core.Binding;
using MediatR;

[Form(Label = "Add 2 numbers", SubmitButtonLabel = "Submit", PostOnLoad = false)]
public class AddNumbers : Form<AddNumbers.Request, AddNumbers.Response>
{
    public class Response : FormResponse
    {
        [OutputField(Label = "Result of your calculation")]
        public long Result { get; set; }
    }

    public class Request : IRequest<Response>
    {
        [InputField(Label = "First number")]
        public int Number1 { get; set; }

        [InputField(Label = "Second number")]
        public int Number2 { get; set; }
    }

    protected override Response Handle(Request message)
    {
        return new Response
        {
            Result = message.Number1 + message.Number2
        };
    }
}
Notice how the form is self-contained. The Request class defines inputs, the Response class defines outputs, and the Handle method implements the business logic.

Step 3: Understanding the code

Let’s break down what each part does:

Form attribute

[Form(Label = "Add 2 numbers", SubmitButtonLabel = "Submit", PostOnLoad = false)]
The FormAttribute decorates your form class and defines:
  • Label - The display name shown to users
  • SubmitButtonLabel - Text for the submit button (optional)
  • PostOnLoad - Whether to auto-submit the form when loaded (useful for reports)

Request class

public class Request : IRequest<Response>
{
    [InputField(Label = "First number")]
    public int Number1 { get; set; }

    [InputField(Label = "Second number")]
    public int Number2 { get; set; }
}
The Request class defines your form’s inputs. Each property decorated with [InputField] becomes an input field in the UI.

Response class

public class Response : FormResponse
{
    [OutputField(Label = "Result of your calculation")]
    public long Result { get; set; }
}
The Response class defines your form’s outputs. Properties decorated with [OutputField] are displayed after the form is submitted.

Handle method

protected override Response Handle(Request message)
{
    return new Response
    {
        Result = message.Number1 + message.Number2
    };
}
This method contains your business logic. It receives the request and returns the response.

Step 4: Generate metadata

To generate metadata for your form, you need to register it with the MetadataBinder and FormRegister:
using UiMetadataFramework.Basic;
using UiMetadataFramework.Basic.Server;
using UiMetadataFramework.Core.Binding;

// Create metadata binder
var binder = new MetadataBinder(new DefaultDependencyInjectionContainer());

// Register the Basic component library
binder.RegisterAssembly(typeof(UiMetadataFramework.Basic.Server.FormResponse).Assembly);

// Create form register and register your form
var formRegister = new FormRegister(binder);
formRegister.RegisterForm(typeof(AddNumbers));

// Get the metadata
var formInfo = formRegister.GetFormInfo(typeof(AddNumbers));
var metadata = formInfo.Metadata;

Step 5: View the generated metadata

The metadata object contains all the information your frontend needs to render the form. Here’s what it looks like as JSON:
{
    "id": "AddNumbers",
    "label": "Add 2 numbers",
    "inputFields": [
        {
            "id": "Number1",
            "label": "First number",
            "type": "number",
            "required": true,
            "hidden": false,
            "orderIndex": 0
        },
        {
            "id": "Number2",
            "label": "Second number",
            "type": "number",
            "required": true,
            "hidden": false,
            "orderIndex": 0
        }
    ],
    "outputFields": [
        {
            "id": "Result",
            "label": "Result of your calculation",
            "type": "number",
            "hidden": false,
            "orderIndex": 0
        }
    ],
    "postOnLoad": false,
    "postOnLoadValidation": true
}
The type field is automatically inferred from the C# property type. For example, int and long properties become "type": "number".

Step 6: How the client uses this metadata

Your frontend client receives this metadata and uses it to:
  1. Render input fields - Create two numeric input fields labeled “First number” and “Second number”
  2. Handle submission - POST the user’s input values to your API endpoint
  3. Display the result - Show the calculated result in an output field
For example, using the uimf-svelte client:
import { FormMetadata } from 'uimf-core';

// Fetch metadata from your API
const response = await fetch('/api/metadata/AddNumbers');
const metadataJson = await response.json();

// Create FormMetadata instance
const formMetadata = new FormMetadata(metadataJson);

// The client renders the form based on this metadata
// Input fields are created from formMetadata.inputFields
// Output fields are created from formMetadata.outputFields

Next steps

Congratulations! You’ve created your first UIMF form. Here’s what to explore next:

Core concepts

Learn about forms, fields, and metadata binding

Input components

Explore different input field types and options

Output components

Learn how to format and display form results

Event handlers

Add dynamic behavior to your forms
Try modifying the AddNumbers form to:
  • Add validation rules using the Required parameter
  • Add more input fields
  • Change the output format
  • Set PostOnLoad = true to auto-submit the form

Build docs developers (and LLMs) love