Skip to main content
AI/MLCrestApps

orchardcore-forms

Skill for building and managing forms in Orchard Core using the OrchardCore.Forms module. Covers form widget content types, form validation, form submissions with workflows, anti-forgery tokens, and custom form elements. Use this skill when requests mention Orchard Core Forms, Create and Configure Forms, Enabling the Forms Feature, Form Widget Content Types, Form Content Type Settings, Input Element Configuration, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with OrchardCore.Forms, OrchardCore.Workflows, OrchardCore.Flows, OrchardCore.Widgets, OrchardCore.Workflows.Http, OrchardCore.ContentManagement, OrchardCore.DisplayManagement.Views, OrchardCore.Modules, OrchardCore.ContentManagement.Metadata. It also helps with forms examples, Form Content Type Settings, Input Element Configuration, Input Element Properties, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.

Stars
13
Source
CrestApps/CrestApps.AgentSkills
Updated
2026-05-29
Slug
CrestApps--CrestApps.AgentSkills--orchardcore-forms
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/CrestApps/CrestApps.AgentSkills/HEAD/plugins/orchardcore/skills/orchardcore-forms/SKILL.md -o .claude/skills/orchardcore-forms.md

Drops the SKILL.md into .claude/skills/orchardcore-forms.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

Orchard Core Forms

Enable OrchardCore.Forms and use its widget types inside a FlowPart. Form contains FormElementPart, FormPart, and FlowPart. Input, Select, and TextArea each contain FormInputElementPart, FormElementPart, FormElementLabelPart, their specific element part, FormElementValidationPart, and FormInputElementVisibilityPart.

Part Current responsibility
FormPart Action, Method, WorkflowTypeId, EncType, anti-forgery, and form-location behavior
FormElementPart Element Id
FormInputElementPart Submitted field Name
InputPart Input Type, DefaultValue, and Placeholder
SelectPart Options, DefaultValue, and Editor

The Form wrapper emits an anti-forgery token when enabled and, by default, the __RequestOriginatedFrom workflow input used by HTTP workflow redirects.

Enable Forms

{
  "steps": [
    {
      "name": "Feature",
      "enable": [
        "OrchardCore.Forms",
        "OrchardCore.Flows",
        "OrchardCore.Widgets",
        "OrchardCore.Workflows",
        "OrchardCore.Workflows.Http"
      ]
    }
  ]
}

Form Element Content

SelectPart.Options is an array of SelectOption objects, not newline text:

{
  "ContentType": "Select",
  "FormInputElementPart": {
    "Name": "ContactReason"
  },
  "FormElementPart": {
    "Id": "contact-reason"
  },
  "SelectPart": {
    "Editor": "Dropdown",
    "DefaultValue": "support",
    "Options": [
      {
        "Text": "Technical support",
        "Value": "support"
      },
      {
        "Text": "Sales",
        "Value": "sales"
      }
    ]
  }
}

Workflow Submission and Validation

Set the form action to a workflow HTTP endpoint and start the workflow with the real HttpRequestEvent; FormSubmissionEvent is not an Orchard Core activity. FormPart.WorkflowTypeId exists on the model, but the built-in editor does not render an input for it; set it through code or imported data when needed. It does not replace an HTTP event route.

Forms supplies these validation activities when OrchardCore.Workflows is enabled:

  • ValidateAntiforgeryTokenTask
  • BindModelStateTask
  • ValidateFormFieldTask
  • AddModelValidationErrorTask
  • ValidateFormTask
  • HttpRedirectToFormLocationTask

In JavaScript workflow expressions, use the HTTP globals requestForm(name) or deserializeRequestData() and workflow globals property(name), setProperty(name, value), and setOutcome(name). Do not use fictional requestFormAsDict, addModelError, or modelState globals.

var email = requestForm("ContactEmail");

if (!email || !email.includes("@")) {
    setOutcome("Invalid");
} else {
    setProperty("ContactEmail", email);
    setOutcome("Valid");
}

For required fields and model-state errors, add ValidateFormFieldTask or AddModelValidationErrorTask in the workflow and then use ValidateFormTask to branch to its Valid or Invalid outcome.

Custom Form Elements

Custom elements are ordinary content parts and widgets. Add the part, display driver, view model, and content type definition; use FormInputElementPart.Name when the element must submit a value. View models remain unsealed for model binding; seal other classes.