OsirionContactForm
OsirionContactForm renders a name, email, subject and message form with a privacy checkbox and an optional
newsletter checkbox. It validates on the server, posts as a normal HTML form under static SSR, and either sends the
message through the built-in email service or hands it to your own callback.
Package Osirion.Blazor.Core, namespace Osirion.Blazor.Components. Source on GitHub.
Ask about the library
This form is a demo: it validates your input like the real one, then sends nothing.
@using Osirion.Blazor.Components
@using Osirion.Blazor.Core.Models
@* A demo: OnSubmit does nothing, so the message goes nowhere, and the success message says so. *@
<OsirionContactForm Id="demo-contact"
FormTitle="Ask about the library"
FormDescription="This form is a demo: it validates your input like the real one, then sends nothing."
PrivacyPolicyText="I understand that this demo keeps nothing"
ShowSubscribeOption="false"
SuccessMessage="This demo sends nothing: your message was not stored or delivered."
OnSubmit="IgnoreAsync" />
@code {
private static Task IgnoreAsync(ContactFormModel message) => Task.CompletedTask;
}The demo validates like the real form, but its OnSubmit handler does nothing, so nothing is sent or stored.
Usage
The smallest form passes the message to your code:
@page "/contact"
@using Osirion.Blazor.Components
@using Osirion.Blazor.Core.Models
<OsirionContactForm Id="contact" OnSubmit="HandleSubmitAsync" />
@code {
private async Task HandleSubmitAsync(ContactFormModel message)
{
// Save the message, queue it or call your CRM here.
// An exception shows ErrorMessage instead of SuccessMessage.
await Task.CompletedTask;
}
}
To have the library send the message by email, register the email service (next section) and set
UseBuiltInEmailService:
<OsirionContactForm Id="contact"
UseBuiltInEmailService="true"
FormTitle="Get in touch"
FormDescription="Questions about the library? Write to us."
PrivacyPolicyText="I agree to the <a href='/privacy'>privacy policy</a>"
ShowSubscribeOption="false"
ContactInfo="contactInfo" />
@code {
private readonly ContactInformation contactInfo = new()
{
Address = "Belgrade, Serbia",
Email = "[email protected]"
};
}
When ContactInfo is set, an OsirionContactInfoSection is
shown next to the form (or below it with SideBySideLayout="false"). Without it, no contact details are rendered.
A form with neither OnSubmit nor UseBuiltInEmailService has nothing to deliver the message with. It does not
claim success: it logs a warning and shows ErrorMessage, so a message is never lost silently.
Email delivery
AddOsirion(builder.Configuration) registers the email service when the Osirion:Email section exists.
Provider is Smtp (the default), SendGrid or Infobip.
{
"Osirion": {
"Email": {
"Provider": "Smtp",
"ToEmail": "[email protected]",
"FromName": "Website contact form",
"SubjectTemplate": "Contact form: {subject}",
"Smtp": {
"Host": "smtp.example.com",
"Port": 587,
"EnableSsl": true,
"Username": "[email protected]",
"FromEmail": "[email protected]"
}
}
}
}
Keep the password or API key out of appsettings.json: put Osirion:Email:Smtp:Password,
Osirion:Email:SendGrid:ApiKey or Osirion:Email:Infobip:ApiKey in user secrets locally, and in environment
variables or a key vault in production.
| Key | Default | Meaning |
|---|---|---|
Provider |
Smtp |
Smtp, SendGrid or Infobip. |
ToEmail |
empty | Where messages are delivered. |
FromName |
Contact Form |
Sender display name. |
SubjectTemplate |
Contact Form: {subject} |
{subject} is replaced with the visitor's subject. |
Smtp: Host, Port, EnableSsl, Username, Password, FromEmail |
port 587, SSL on |
SMTP server settings. |
SendGrid: ApiKey, FromEmail |
empty | SendGrid settings. |
Infobip: BaseUrl, ApiKey, FromEmail |
BaseUrl is https://api.infobip.com |
Infobip settings. |
You can also configure it in code with UseEmailServices:
using Osirion.Blazor.Core.Configuration;
using Osirion.Blazor.Extensions;
builder.Services.AddOsirion(osirion => osirion.UseEmailServices(email =>
{
email.Provider = EmailProviderType.SendGrid;
email.ToEmail = "[email protected]";
email.SendGrid.FromEmail = "[email protected]";
email.SendGrid.ApiKey = builder.Configuration["Osirion:Email:SendGrid:ApiKey"] ?? string.Empty;
}));
Without the Osirion.Blazor meta-package, services.AddOsirionEmailServices(configuration) from
Osirion.Blazor.Core.Extensions does the same. The mail is HTML, every visitor value in it is HTML-encoded, and the
visitor's address is set as Reply-To, so you can answer directly. SendGrid and Infobip calls time out after 30
seconds.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Id |
string |
"contact-form" |
The form name and the prefix of every field id, such as contact-name-contact. Required; use a unique value for each form on a page. |
FormTitle |
string |
"Write us" |
The heading (h2) above the form. An empty value hides it. |
FormDescription |
string |
"" |
The text under the heading. Empty by default, which renders nothing. |
NamePlaceholder |
string |
"Your name" |
The placeholder of the name field. |
EmailPlaceholder |
string |
"Your email address" |
The placeholder of the email field. |
SubjectPlaceholder |
string |
"Subject" |
The placeholder of the subject field. |
MessagePlaceholder |
string |
"Your message" |
The placeholder of the message field. |
MessageRows |
int |
6 |
The number of rows of the message textarea. |
SubmitButtonText |
string |
"Send Message" |
The text of the submit button. |
SubmittingText |
string |
"Sending..." |
A text for the submit button while sending. Not used by the current markup. |
ShowResetButton |
bool |
false |
Whether a reset button, which clears the fields in the browser, is shown next to the submit button. |
ResetButtonText |
string |
"Reset" |
The text of the reset button. |
ShowRequiredIndicators |
bool |
true |
Whether a * follows the label of each required field and of the privacy checkbox. |
PrivacyPolicyText |
string? |
"I agree to the <a href="/privacy-policy" target="_blank">privacy policy</a>" |
The label of the privacy checkbox, rendered as raw HTML, so pass only text you wrote. The default text links to /privacy-policy. The checkbox is left out when the value is null or empty, and the form then submits without it: ContactFormModel.AgreeToPrivacyPolicy is set to true so the model validates, which means it records no consent and must not be stored as consent. |
ShowSubscribeOption |
bool |
true |
Whether the newsletter checkbox is shown. Its value reaches your code as ContactFormModel.SubscribeToUpdates. |
SubscribeText |
string |
"I would like to receive updates and newsletters" |
The label of the newsletter checkbox. |
ShowContactInformation |
bool |
true |
Whether the contact information section is shown when ContactInfo is set. |
ContactInfoTitle |
string |
"Contact information" |
The title of the contact information section. |
ContactInfo |
ContactInformation? |
null |
The address, phone, email, website and message shown beside or below the form. When it is null, which is the default, no contact information section is rendered; the form never invents placeholder details. |
OnSubmit |
EventCallback<ContactFormModel> |
- | The callback that receives the validated message. It runs for a submission that is valid and whose honeypot field is empty. With UseBuiltInEmailService it runs after the email was sent; without it, it is the only delivery. When it throws, ErrorMessage is shown. Without it, and without UseBuiltInEmailService, nothing can deliver the message, so the form reports an error. |
OnReset |
EventCallback |
- | A callback for a form reset. Not used by the current markup. |
OnValidationFailed |
EventCallback<EditContext> |
- | A callback for failed validation. Not used by the current markup. |
SuccessMessage |
string |
"Thank you! Your message has been sent successfully. We'll get back to you soon." |
The message shown after a successful submission. |
ErrorMessage |
string |
"Sorry, there was an error sending your message. Please try again later." |
The message shown when sending fails, when OnSubmit throws, or when nothing can deliver the message. |
SpamMessage |
string |
"Your submission appears to be spam and has been blocked." |
The message shown when the hidden honeypot field was filled. Nothing is sent and OnSubmit is not called. |
UseBuiltInEmailService |
bool |
false |
Whether the message is sent through the email service registered with AddOsirion or AddOsirionEmailServices (SMTP, SendGrid or Infobip). When the service is not registered, the form logs a warning and shows ErrorMessage. |
SideBySideLayout |
bool |
true |
Whether the contact information sits beside the form (true, the default) or below it. |
UseDarkTheme |
bool |
false |
Whether the form uses its dark palette instead of the theme colors. |
Theme |
ThemeMode |
ThemeMode.System |
The component's color mode. Light or Dark writes it to data-theme (data-bs-theme under Bootstrap) on the root element; System writes nothing. |
Class |
string? |
null |
Extra CSS classes for the component's root element. |
Style |
string? |
null |
An inline style for the component's root element. |
ContactFormModel, which OnSubmit receives, has Name, Email, Subject, Message, AgreeToPrivacyPolicy,
SubscribeToUpdates and the honeypot field Website.
Behavior
- Static SSR. The form is an
EditFormwithFormNameset toId, so it posts and validates on the server without script. After a valid post the component redirects to the same page with aSubmissionResultValuequery value, and the page shows the success, error or spam message. Invalid fields show their messages in place. - Validation comes from data annotations on
ContactFormModel: a name up to 100 characters, a valid email up to 255, a subject up to 200, a message of 10 to 5,000 characters, and a ticked privacy checkbox. - Spam. A hidden
Websitefield acts as a honeypot. When a bot fills it, nothing is sent,OnSubmitis not called andSpamMessageis shown. - When nothing can deliver the message. The form reports
ErrorMessage, never success and never the spam message, in two cases: neitherOnSubmitnorUseBuiltInEmailServiceis set, orUseBuiltInEmailServiceistrueand no email service is registered. Both log a warning. A failed send, or an exception fromOnSubmit, showsErrorMessagetoo and is logged as an error. - Both delivery paths. With
UseBuiltInEmailService="true",OnSubmitis called only after the email was sent, so you can also log or store the message. - Accessibility. Every field has a
label, and each input points to its validation message witharia-describedby. Status icons are hidden from assistive technology; the message text carries the meaning.
Warning
PrivacyPolicyText is rendered as raw HTML. Use only text you wrote; never pass visitor or CMS input.
Note
Set PrivacyPolicyText to null or empty to leave the checkbox out. The form then submits without it, and
AgreeToPrivacyPolicy on the model OnSubmit receives is true so the model validates. It then records no
consent, so do not store it as consent. Keep the checkbox if you need the visitor's consent.
Rate-limit the page that hosts the form: the honeypot stops simple bots, not a determined sender.
Styling
The outer element has osirion-contact-form-container plus osirion-contact-form-side-by-side or
osirion-contact-form-stacked, and osirion-contact-form-dark with UseDarkTheme. Override the form's custom
properties on the container:
.osirion-contact-form-container {
--osirion-contact-accent: #0e7490;
--osirion-contact-radius: 0;
}
The properties are --osirion-contact-bg, --osirion-contact-form-bg, --osirion-contact-text,
--osirion-contact-text-muted, --osirion-contact-border, --osirion-contact-accent, --osirion-contact-radius and
--osirion-contact-spacing. In the light palette they default to the theme tokens (--osirion-background-primary,
--osirion-text-primary, --osirion-action-primary and so on), so a CSS framework adapter recolors the form. Buttons
and the status message use the active framework's classes.