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.
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()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 eventsdrawFrame() — 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, FontFamilyInstall-Package Syncfusion.EJ2.AspNet.Core
~/Pages/_ViewImports.cshtml)@addTagHelper *, Syncfusion.EJ2
~/Pages/Shared/_Layout.cshtml)Local Assets Only (Required for Security Compliance)
Download the Syncfusion EJ2 distribution from the official release and host locally:
<head>
<!-- CSS hosted locally in wwwroot/lib/ej2/ -->
<link rel="stylesheet" href="/lib/ej2/fluent2.css" />
</head>
<body>
...
<!-- JavaScript hosted locally in wwwroot/lib/ej2/ -->
<!-- IMPORTANT: Do NOT load from external CDN — use local assets only -->
<script src="/lib/ej2/ej2.min.js"></script>
<ejs-scripts></ejs-scripts>
</body>
⚠️ Security Policy: External CDN loading is not permitted. All Syncfusion runtime assets must be hosted locally in your application.
~/Pages/Index.cshtml)<div class="e-img-editor-sample">
<ejs-imageeditor id="image-editor"></ejs-imageeditor>
</div>
<style>
.e-img-editor-sample {
height: 80vh;
width: 100%;
}
</style>
Option A: Local Image File (Recommended)
<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>
Option B: User-Uploaded Image (Base64)
<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>
| 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:
// ❌ 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
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:
// ✅ 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);
}
}
Validate all image uploads server-side before processing:
// 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();
}
When using drawImage() for logos or watermarks, reference only local assets:
// ✅ 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', ...);
Restrict all content sources to local/trusted origins:
<!-- Enforce local-only content loading -->
<meta http-equiv="Content-Security-Policy"
content="script-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';">
| 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.