This example adds a custom action button to the Document Viewer that triggers a custom operation on the server side. The server-side custom operation exports a report to HTML and PDF, and emails the resulting documents.
When you run the application, you observe the Document Viewer with a newly added action button:
To email a report, click the button. The application attempts to send email to someone@test.com
using the localhost
SMTP server, port 25. Modify the code to apply your mail server settings.
The report sent by email is shown in the following image:
When the user clicks the 'Send via Email' button, the client-side PerformCustomDocumentOperation method passes data to the DocumentOperationService on the server. The service exports the report to PDF and HTML formats, creates the MIME message and sends email using the MailKIt client.
The PerformCustomDocumentOperation method returns an object that implements the IDocumentOperationResult interface, so you can return the data from the DocumentOperationService to the client.
Files to Review
- Global.asax.cs (VB: Global.asax.vb)
- CustomDocumentOperationService.cs (VB: CustomDocumentOperationService.vb)
- Viewer.cshtml (VB: Viewer.vbhtml)
Documentation
More Examples
- Reporting for WinForms - How to Use MailKit to Email a Report
- Reporting for Blazor - Email a Report from the Native Blazor Report Viewer
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using DevExpress.Web.Mvc;
using DevExpress.XtraReports.Services;
using DevExpress.XtraReports.Web.WebDocumentViewer;
namespace DocumentOperationServiceSample {
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {
DevExpress.XtraReports.Web.WebDocumentViewer.Native.WebDocumentViewerBootstrapper.SessionState = System.Web.SessionState.SessionStateBehavior.Default;
DefaultWebDocumentViewerContainer.Register<DocumentOperationService, Services.CustomDocumentOperationService>();
DevExpress.XtraReports.Web.WebDocumentViewer.DefaultWebDocumentViewerContainer.Register<IReportProvider, Services.ReportProvider>();
MVCxWebDocumentViewer.StaticInitialize();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder();
DevExpress.Web.ASPxWebControl.CallbackError += Application_Error;
}
protected void Application_Error(object sender, EventArgs e) {
Exception exception = System.Web.HttpContext.Current.Server.GetLastError();
//TODO: Handle Exception
}
}
}
C#using System;
using System.IO;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.Web.WebDocumentViewer;
using DevExpress.XtraReports.Web.WebDocumentViewer.DataContracts;
using MailKit.Security;
namespace DocumentOperationServiceSample.Services {
public class CustomDocumentOperationService : DocumentOperationService {
public override bool CanPerformOperation(DocumentOperationRequest request) {
return true;
}
public override DocumentOperationResponse PerformOperation(DocumentOperationRequest request,
PrintingSystemBase initialPrintingSystem,
PrintingSystemBase printingSystemWithEditingFields) {
using (var stream = new MemoryStream()) {
System.Net.Mail.MailMessage mMessage =
printingSystemWithEditingFields.ExportToMail(request.CustomData,
"john.doe@test.com",
"John Doe");
mMessage.Subject = "Test";
// Create a new attachment and add the PDF document.
printingSystemWithEditingFields.ExportToPdf(stream);
stream.Seek(0, System.IO.SeekOrigin.Begin);
System.Net.Mail.Attachment attachedDoc =
new System.Net.Mail.Attachment(stream, "TestReport.pdf", "application/pdf");
mMessage.Attachments.Add(attachedDoc);
var message = (MimeKit.MimeMessage)mMessage;
string smtpHost = "localhost";
int smtpPort = 25;
using (message) {
using (var client = new MailKit.Net.Smtp.SmtpClient()) {
try {
client.Connect(smtpHost, smtpPort, SecureSocketOptions.Auto);
//client.Authenticate(userName, password);
client.Send(message);
client.Disconnect(true);
return new DocumentOperationResponse {
Succeeded = true,
Message = "Mail was sent successfully",
DocumentId = printingSystemWithEditingFields.Document.Name
};
}
catch (Exception ex) {
return new DocumentOperationResponse {
Message = ex.Message,
Succeeded = false,
};
}
}
}
}
}
protected string RemoveNewLineSymbols(string value) {
return value;
}
}
}
Razor<style>
.custom-image-item {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjYgMjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI2IDI2OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe2ZpbGw6IzNEM0QzRDt9PC9zdHlsZT48Zz48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMjUsN2MwLTAuMi0wLjEtMC42LTAuMy0wLjdDMjQuNiw2LjEsMjQuNCw2LDI0LjIsNkgxNnY1LjdsMS45LDEuN0wyNSw3eiIvPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xLDIybDE0LDNWMUwxLDRWMjJ6IE04LDEwYzEuNywwLDMsMS44LDMsNGMwLDIuMi0xLjMsNC0zLDRzLTMtMS44LTMtNEM1LDExLjgsNi4zLDEwLDgsMTB6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTE4LDE1bC0yLTJsMCw4bDguMiwwYzAuMiwwLDAuNC0wLjEsMC42LTAuM2MwLjItMC4yLDAuMi0wLjQsMC4yLTAuNkwyNSw5TDE4LDE1TDE4LDE1eiIvPjxlbGxpcHNlIGNsYXNzPSJzdDAiIGN4PSI4IiBjeT0iMTQiIHJ4PSIyIiByeT0iMyIvPjwvZz48L3N2Zz4NCg==);
background-repeat: no-repeat;
}
</style>
<script>
function CustomizeMenuActions(s, e) {
var itemDisabled = ko.observable(true);
s.Init.AddHandler(function (s) {
var reportPreview = s.GetReportPreview();
reportPreview.events.on('propertyChanged', (e) => {
if(e.propertyName === 'exportDisabled') {
itemDisabled(e.newValue);
}
});
itemDisabled(reportPreview.exportDisabled);
});
var sendViaEmailItem = {
id: 'someCustomId',
imageClassName: 'custom-image-item',
text: 'Send via Email',
visible: true,
disabled: itemDisabled,
clickAction: function () {
var previewModel = s.GetPreviewModel();
s.PerformCustomDocumentOperation('someone@test.com')
.then((arg) => alert('Document ' + arg.documentId + " : " + arg.message));
}
};
e.Actions.push(sendViaEmailItem);
}
</script>
@Html.DevExpress().WebDocumentViewer(settings => {
settings.Name = "WebDocumentViewer1";
settings.ClientSideEvents.CustomizeMenuActions = "CustomizeMenuActions";
}).Bind("CategoriesReport").GetHtml()
Code<style>
.custom-image-item {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjYgMjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI2IDI2OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe2ZpbGw6IzNEM0QzRDt9PC9zdHlsZT48Zz48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMjUsN2MwLTAuMi0wLjEtMC42LTAuMy0wLjdDMjQuNiw2LjEsMjQuNCw2LDI0LjIsNkgxNnY1LjdsMS45LDEuN0wyNSw3eiIvPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xLDIybDE0LDNWMUwxLDRWMjJ6IE04LDEwYzEuNywwLDMsMS44LDMsNGMwLDIuMi0xLjMsNC0zLDRzLTMtMS44LTMtNEM1LDExLjgsNi4zLDEwLDgsMTB6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTE4LDE1bC0yLTJsMCw4bDguMiwwYzAuMiwwLDAuNC0wLjEsMC42LTAuM2MwLjItMC4yLDAuMi0wLjQsMC4yLTAuNkwyNSw5TDE4LDE1TDE4LDE1eiIvPjxlbGxpcHNlIGNsYXNzPSJzdDAiIGN4PSI4IiBjeT0iMTQiIHJ4PSIyIiByeT0iMyIvPjwvZz48L3N2Zz4NCg==);
background-repeat: no-repeat;
}
</style>
<script>
function CustomizeMenuActions(s, e) {
var itemDisabled = ko.observable(true);
s.Init.AddHandler(function (s) {
var reportPreview = s.GetReportPreview();
reportPreview.events.on('propertyChanged', (e) => {
if(e.propertyName === 'exportDisabled') {
itemDisabled(e.newValue);
}
});
itemDisabled(reportPreview.exportDisabled);
});
var sendViaEmailItem = {
id: 'someCustomId',
imageClassName: 'custom-image-item',
text: 'Send via Email',
visible: true,
disabled: itemDisabled,
clickAction: function () {
s.PerformCustomDocumentOperation('someone@test.com')
.done((arg) => alert('Document ' + arg.documentId + " : " + arg.message));
}
};
e.Actions.push(sendViaEmailItem);
}
</script>
@Html.DevExpress().WebDocumentViewer(
Sub(settings)
settings.Name = "WebDocumentViewer1"
settings.ClientSideEvents.CustomizeMenuActions = "CustomizeMenuActions"
End Sub).Bind("CategoriesReport").GetHtml()