npx skills add ...
npx skills add syncfusion/aspnetcore-ui-components-skills --skill syncfusion-aspnetcore-image-editor
Implement the Syncfusion ASP.NET Core Image Editor (EJ2) component. Use this when adding image editing to an ASP.NET Core application, including cropping, rotating, annotations, fine-tuning (brightness, contrast, blur), and filter application. Covers opening/saving images, toolbar customization, redaction, resizing, and image editor event handling with ejs-imageeditor.
npx skills add syncfusion/aspnetcore-ui-components-skills --skill syncfusion-aspnetcore-image-editor
The Syncfusion EJ2 Image Editor provides a rich, interactive image editing experience directly in the browser. It supports opening, editing, and saving images in PNG, JPEG, SVG, WEBP, and BMP formats. All actions—including annotations, transformations, and filters—are tracked in a 16-step undo/redo history.
📄 Read: references/getting-started.md
_ViewImports.cshtml<ejs-imageeditor> tag📄 Read: references/open-save.md
open() method — local file, base64, Blob, URL, File Uploader, File ManagerimageSettingsexport() — save with format and quality optionsgetImageData() — retrieve image as base64 / BlobclearImage() and reset() patternsFileOpened, Saving, and BeforeSave events📄 Read: references/transform.md
rotate() — clockwise/anti-clockwise in degreesflip() — Horizontal or VerticalstraightenImage() — ±45° range for alignmentzoom() — magnify with optional zoom pointZoomSettings — minZoomFactor, maxZoomFactorRotating, Flipping, Zooming, Panning events📄 Read: references/selection-cropping.md
select() — custom, square, circle, aspect ratio typescrop() — execute crop on selected regionpreventScaling)SelectionChanging event — programmatic selection adjustments📄 Read: references/annotation.md
drawText() — text with font, size, bold, italic, underline, strikethrough, fill, stroke\n in text contentdrawRectangle(), drawEllipse(), drawLine(), drawArrow(), drawPath()drawImage() — overlay images, logos, watermarksfreehandDraw() — enable/disable freehand drawing modedeleteShape() / getShapeSetting() — manage annotationsFontFamily property — add custom font familiesShapeChanging / ShapeChange events📄 Read: references/finetune-filter.md
finetuneImage() — brightness, contrast, saturation, hue, exposure, blur, opacityFinetuneSettings property for configuring available fine-tune optionsapplyImageFilter() — cold, warm, chrome, sepia, grayscale, invertFinetuneValueChanging eventImageFiltering event with cancel support📄 Read: references/resize-redact.md
resize() — width, height, aspect ratio controlResizing event with before/after dimensionsdrawRedact() — blur or pixelate sensitive areasselectRedact(), deleteRedact(), updateRedact(), getRedacts()📄 Read: references/toolbar-quickaccess.md
Toolbar property — add, remove, or hide toolbar itemsToolbarTemplate — replace entire toolbar with custom HTMLToolbarUpdating event — customize contextual toolbarsShowQuickAccessToolbar — toggle quick access toolbarQuickAccessToolbarOpen event — add custom items to quick access toolbarToolbarCreated / ToolbarItemClicked events📄 Read: references/frames-localization-accessibility.md
drawFrame() — mat, bevel, line, hook, inset frame typesUploadSettings — restrict file extensions and file sizesLocale property — internationalization with translation objectsundo() / redo() methods and AllowUndoRedo property (16-step history)📄 Read: references/api.md
AllowUndoRedo, CssClass, Disabled, Height, Width, Theme, LocaleZoomSettings, FinetuneSettings, SelectionSettings, UploadSettings, FontFamily~/Pages/_ViewImports.cshtml)~/Pages/Shared/_Layout.cshtml)Local Assets Only (Required for Security Compliance)
Download the Syncfusion EJ2 distribution from the official release and host locally:
⚠️ Security Policy: External CDN loading is not permitted. All Syncfusion runtime assets must be hosted locally in your application.
~/Pages/Index.cshtml)Option A: Local Image File (Recommended)
Option B: User-Uploaded Image (Base64)
| Property | Type | Default | Purpose |
|---|---|---|---|
height | string | "100%" | Editor height |
width | string | "100%" | Editor width |
allowUndoRedo | bool | true | Enable undo/redo (16 steps) |
disabled | bool | false | Disable the control |
showQuickAccessToolbar | bool | true | Show annotation quick access toolbar |
theme | Theme | Bootstrap5 | Shape selection appearance theme |
locale | string | "en-US" | Localization culture |
imageSmoothingEnabled | bool | false | High-quality rendering smoothing |
toolbar | object | default items | Toolbar items array |
toolbarTemplate | string | null | Custom toolbar template selector |
DO NOT use imageEditor.open() or drawImage() with external/untrusted URLs:
External URLs create supply-chain and injection risks that cannot be fully mitigated.
CRITICAL POLICY: This skill requires all runtime code and content to be sourced locally.
The Syncfusion EJ2 runtime library MUST be hosted locally:
wwwroot/lib/ej2//lib/ej2/ej2.min.js (local path only)Load user-uploaded files locally and pass as base64 or Blob to avoid any external fetches:
Validate all image uploads server-side before processing:
When using drawImage() for logos or watermarks, reference only local assets:
Restrict all content sources to local/trusted origins:
| Factor | Assessment |
|---|---|
| Vendor | Syncfusion Inc. — established enterprise component vendor, widely adopted |
| Protocol | All CDN resources served over HTTPS with certificate pinning possible |
| Transparency | Regular security updates and CVE disclosures via Syncfusion support channels |
| Monitoring | Check Syncfusion security bulletins and NuGet package advisory database |
| Undo/Redo | 16-step history is local-only; no cloud sync or external telemetry |
✅ Runtime Asset Security
wwwroot/lib/ej2/✅ Content & Image Security
wwwroot/images/ for all application images✅ Compliance & Monitoring
script-src 'self'; img-src 'self' data:snyk, dotnet list package --vulnerable, etc.<div class="e-img-editor-sample">
<ejs-imageeditor id="image-editor"></ejs-imageeditor>
</div>
<style>
.e-img-editor-sample {
height: 80vh;
width: 100%;
}
</style><ejs-imageeditor id="image-editor" created="onCreated"></ejs-imageeditor>
<script>
function onCreated() {
var imageEditor = document.getElementById('image-editor').ej2_instances[0];
// Reference local image in wwwroot/images/
imageEditor.open('/images/nature.png');
}
</script><ejs-uploader id="fileUpload" selected="onFileSelected"></ejs-uploader>
<ejs-imageeditor id="image-editor"></ejs-imageeditor>
<script>
function onFileSelected(args) {
if (args.filesData.length > 0) {
var reader = new FileReader();
reader.onload = function() {
// Pass base64-encoded local data (no external fetch)
var imageEditor = document.getElementById('image-editor').ej2_instances[0];
imageEditor.open(reader.result);
};
reader.readAsDataURL(args.filesData[0].rawFile);
}
}
</script><button onclick="saveImage()">Save</button>
<ejs-imageeditor id="image-editor" created="onCreated"></ejs-imageeditor>
<script>
function onCreated() {
var imageEditor = document.getElementById('image-editor').ej2_instances[0];
// Load local image
imageEditor.open('/images/nature.png');
}
function saveImage() {
var imageEditor = document.getElementById('image-editor').ej2_instances[0];
imageEditor.export('PNG'); // saves as PNG to local device
}
</script><ejs-imageeditor id="image-editor" fileOpened="onFileOpened"></ejs-imageeditor>
<script>
function onFileOpened(args) {
console.log('Opened file:', args.fileName, 'Type:', args.fileType);
}
</script><ejs-imageeditor id="image-editor">
<e-imageeditor-uploadsettings allowedExtensions=".jpg, .png, .webp"
minFileSize="10000"
maxFileSize="5000000">
</e-imageeditor-uploadsettings>
</ejs-imageeditor>// ❌ FORBIDDEN — Loads remote content from untrusted sources
imageEditor.open('https://untrusted-external-cdn.com/bridge.png');
imageEditor.open('https://example.com/user-uploads/image.jpg'); // Arbitrary external URL
imageEditor.drawImage('https://external-site.com/logo.png', 10, 10, 100, 50);
// ✅ SAFE — Use only local/trusted sources
imageEditor.open('/images/local-image.png'); // Local file in wwwroot
imageEditor.open(base64DataUrl); // Base64 encoded (local data)
imageEditor.open(blobUrl); // Blob URL from File input
imageEditor.drawImage('/images/company-logo.png', 10, 10, 100, 50); // Local asset// ✅ SAFE: Load user file locally as base64
function selected(args) {
if (args.filesData.length > 0) {
var reader = new FileReader();
reader.onload = function() {
imageEditor.open(reader.result); // Base64 data, not URL
};
reader.readAsDataURL(args.filesData[0].rawFile);
}
}// ASP.NET Core controller
[HttpPost]
public IActionResult ValidateImage(IFormFile file)
{
// Whitelist allowed MIME types only
var allowedTypes = new[] { "image/png", "image/jpeg", "image/webp", "image/bmp" };
if (!allowedTypes.Contains(file.ContentType))
return BadRequest("Invalid image format");
// Enforce file size limits (e.g., max 5MB)
if (file.Length > 5 * 1024 * 1024)
return BadRequest("File too large");
return Ok();
}// ✅ SAFE: Local asset in wwwroot/images/
imageEditor.drawImage('/images/company-logo.png', 10, 10, 100, 50);
// ❌ FORBIDDEN: External URLs not permitted
// imageEditor.drawImage('https://external-site.com/logo.png', ...); <!-- Enforce local-only content loading -->
<meta http-equiv="Content-Security-Policy"
content="script-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';">