Table of Contents

Legacy Component Model (deprecated)

Warning

This is the legacy component model from the pre-React era. New components must use the React-era contracts documented in Component Authoring. This page is preserved only as a reference for maintaining surviving legacy MVC components that still ship in older customer customisations.

The legacy model defined a component as a C# class implementing one or more of four behaviour interfaces:

Interface Behaviour
IRenderableComponent Renders the component as HTML via a Razor view.
IRefreshableComponent Supports the legacy MIB.Template.Manager.RefreshComponentView JS call.
IPersistableComponent Handles save / delete via the legacy save pipeline.
IHandlerComponent Exposes a custom server endpoint at /Handler/<pageKey>/<templateComponentKey>.

All four interfaces are still present in MediaiBox.Cms.FrontEnd.Model.Mvc for back-compat. The modern path uses IRenderableComponentV2<TConfig, TData, TSchema> and related interfaces — see Component Authoring.

Required NuGet package

MediaiBox.Cms.FrontEnd.Model.Mvc

Basic component information

All legacy components have a Context property carrying:

  • The currently logged-in user
  • The list of selected ids (in edit mode)
  • The application's root URL

And a Configuration property holding the per-component settings. Configuration values are by default exposed as a Dictionary<string, object>. To use a typed configuration class instead, implement the generic form of the interface (IPersistableComponent<TConfiguration>). Supported configuration property types:

  • string
  • bool
  • int
  • long
  • Uri — relative URLs are resolved against the application root URL.

Accessing the API

Every legacy component implements the same Initialize hook:

public void Initialize(
    IMibApiClientLibrary apiClientLibrary,
    IPublicWorkflowFactory workflowFactory,
    IHttpContextAccessor httpContextAccessor);

The injected IMibApiClientLibrary is how the component reads / writes from the Data API.

IRenderableComponent

Implementations declare a Razor view and return its data:

public ContextViewData Context { get; set; }
public ComponentConfiguration Configuration { get; set; }
public ComponentDisplayMode DisplayMode => ComponentDisplayMode.Edit;

public IInformationRequest GetInformationRequests();

public ComponentRenderData<NameValueCollection> GetRenderData(
    List<ResponseItemContent> responseItemContents);

public List<string> GetStyles();
public List<string> GetScripts();

public ComponentPermission GetPermissions(
    List<ResponseItemContent> responses);

public void Initialize(
    IMibApiClientLibrary apiClientLibrary,
    IPublicWorkflowFactory workflowFactory,
    IHttpContextAccessor httpContextAccessor);

ContextViewData

Stores context data (current user, ids, root URL).

ComponentConfiguration

Stores component-instance settings.

ComponentDisplayMode

public enum ComponentDisplayMode
{
    List,
    Edit,
    Any
}

GetInformationRequests

Returns an IInformationRequest describing the data this component wants the BFF to batch-load before rendering. The legacy pipeline collected requests across components and issued a multipart request to the Data API.

ComponentRenderData

string Title;
string ElementID;
string ViewName;
object ViewData;

Title is the display name. Every legacy component must render inside a card wrapper:

<div class="card" id="myID">
   <!-- Component Body -->
</div>

ElementID must be the id of the card the component renders.

GetStyles / GetScripts

Return lists of CSS and JavaScript URLs the BFF injects into the page when the component is present. These are global per-page (not scoped). The modern path replaces this with bundled imports inside a federated React remote — see Shipping Custom JavaScript.

GetPermissions

Returns a ComponentPermission summarising the user's access:

Read
Create
Write
Delete

Each maps to one of:

public enum PermissionType
{
    Deny     = -1,
    DontCare = 1,
    Allow    = 2
}

IRefreshableComponent

Adds a method to support the legacy MIB.Template.Manager.RefreshComponentView JavaScript call:

ComponentRenderData<TViewData> GetRefreshRenderData(
    PostbackComponentRequest request);

PostbackComponentRequest:

public string TemplateComponentKey { get; set; }
public string JsonData { get; set; }

The React-era replacement is IRefreshableComponentV2<TConfig, TViewData> paired with the props.refresh?.() callback the React shell passes to widgets. See Component Authoring — Refresh.

IPersistableComponent

Adds save / delete handling. Currently limited to one item per component. Methods:

public IPersistenceSaveData Save(
    PostbackComponentRequest request,
    List<IPersistenceSaveData> saveDataList);

public PostbackComponentResponse OnAfterSave(
    List<PersistenceComponentResult> results);

public IPersistenceDeleteData Delete(
    PostbackComponentRequest request,
    List<IPersistenceDeleteData> deleteDataList);

public PostbackComponentResponse OnAfterDelete(
    List<PersistenceComponentResult> results);

Save returns the data to be persisted; OnAfterSave returns information for the legacy client-side JS to display results. OnAfterSave must not return null — if you're not sending additional data, forward the status from the previous request:

public PostbackComponentResponse OnAfterSave(PersistenceComponentResult result)
{
    return new PostbackComponentResponse
    {
        TemplateComponentKey = result.TemplateComponentKey,
        Status = result.Status,
    };
}

Server-side validation lives inside Save. On a validation failure throw PersistenceValidationException — when any component on a page throws this, the whole save is cancelled and every component receives a save-error notification.

PersistenceComponentResult

public class PersistenceComponentResult
{
    public string ResponseIdentifier { get; set; }
    public PostbackStatus Status { get; set; }
    public IPersistenceResponse Response { get; set; }
    public bool IsThereAnErrorInSomeOtherComponent { get; set; }
}
Property Meaning
ResponseIdentifier Identifier of the response.
Status Status of the response.
Response Response content.
IsThereAnErrorInSomeOtherComponent true if any other component on the page failed during the same save.

The React-era replacement for IPersistableComponent is the shell-level useContentEdition().onSave() hook — see React Hooks & Events — useContentEdition.

IHandlerComponent

Allows a component to expose a server endpoint at a fixed route:

/Handler/<pageKey>/<templateComponentKey>

The component implements:

IHandler GetHandler();

with IHandler being:

ActionResult Get(HttpRequestBase request);
ActionResult Post(HttpRequestBase request);
ActionResult Put(HttpRequestBase request);
ActionResult Delete(HttpRequestBase request);

The client-side helper for generating the URL is MIB.Template.Manager.GetHandlerUrl(templateComponentKey).

The modern path replaces this with adding endpoints directly to the customisation's ASP.NET Core routing pipeline — there is no framework-imposed routing template anymore.

Migration to the React-era model

The mapping from legacy interfaces to their modern equivalents:

Legacy Modern
IRenderableComponent.GetRenderData returning a Razor ComponentRenderData IRenderableComponentV2<TConfig, TData, TSchema>.MapSchema + MapData returning typed DTOs that flow as JSON to a React widget — see Component Authoring
IRefreshableComponent.GetRefreshRenderData IRefreshableComponentV2<TConfig, TViewData>.MapRefreshData paired with props.refresh?.()
IPersistableComponent.Save / OnAfterSave The shell's useContentEdition().onSave() hook, with the framework's standard persist pipeline handling the round-trip
IHandlerComponent.GetHandler A standard ASP.NET Core controller / minimal-API endpoint in the customisation
GetStyles() / GetScripts() Bundled imports inside the federated React remote — see Shipping Custom JavaScript
GetPermissions returning Allow/Deny/DontCare IHideableComponent.ShouldHideComponent + MediaTypeInformation.Permissions flags
PersistenceValidationException Throw from inside the modern persist pipeline or use a Custom Validation plugin

For the legacy JavaScript API surface that paired with these interfaces (MIB.Template.Manager.*), see Legacy JavaScript API.

See also