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.
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.
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Forms",
"OrchardCore.Flows",
"OrchardCore.Widgets",
"OrchardCore.Workflows",
"OrchardCore.Workflows.Http"
]
}
]
}
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"
}
]
}
}
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:
ValidateAntiforgeryTokenTaskBindModelStateTaskValidateFormFieldTaskAddModelValidationErrorTaskValidateFormTaskHttpRedirectToFormLocationTaskIn 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 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.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer