Standard and Custom Saving

  • 5 minutes to read

This topic describes different save scenarios that you can implement for office controls.

Simple Save Scenario

In the simplest application scenario, office controls perform document save operations without custom coding. For instance, if an office control opens a document from the server's local file system (using the Open(pathToDocument) method), the document is then saved by the office control to the same file from which it was opened (based on the pathToDocument parameter of the Open method). In this case, click the Save ribbon command in the UI or call the Save() method of an office control to save the edited document to its original file.

Save Methods

More complex application scenarios might require additional coding and use more specific save methods. You can use the Save method and SaveCopy method overloads listed below to programmatically save a document.

Save Method

The Save method initiates a save operation for an office control's active document. In the simple scenario described above, this method successfully saves a document that was opened from the server file system, whose DocumentId equals the document's file path. If the edited document's DocumentId is not specified (e.g., if it is a new document or a document that was not opened from the server's file system), the office control will throw a specific exception. In this instance, use the Saving event to implement custom saving logic.

SaveCopy Method

You can use SaveCopy method overloads to save a copy of an open document to the server file system or an external storage. Specify the copy's destination by selecting the SaveCopy method overload with the required parameters. You can call this method for an active document in an office control (with the control's SaveCopy method) or for any open document currently maintained by DocumentManager (with the SaveCopy method of the IDocumentInfo that identifies the document). In certain cases, the SaveCopy method may lead to multi-user conflicts, which arise when an end user changes and saves a document opened by other users. To resolve this conflict, use the Saving event to implement custom saving logic.

Custom Saving - Using the Saving Event

A custom implementation is required when an office control does not have enough information to complete the document save operation automatically. Such situations occur when an office control tries to save a document that was opened from a custom document storage (such as a database) – and not from the server file system – via the following Open method overloads.

Open(string documentId, DocumentFormat format, Func<Stream> contentAccessor)

Open(string documentId, DocumentFormat format, Func<byte[]> contentAccessor)

Office controls expose the Saving server-side event, which enables you to handle document save operations in a custom manner. The event argument's e.DocumentID property (DocumentSavingEventArgs.DocumentID) identifies the document to be saved. Implement custom save logic and set the e.Handled property (DocumentSavingEventArgs.Handled) to true in the Saving event handler.

The example below shows how to save a document as a byte array:

public static class SaveHelper {
    public static void OnSaving(object source, DevExpress.Web.Office.DocumentSavingEventArgs e) {

        var spreadsheet = (ASPxSpreadsheet)source;

        // Get the document content to be saved as a byte array
        byte[] documentContentAsByteArray = spreadsheet.SaveCopy(DocumentFormat.Xlsx);
        SaveToCustomStorage(documentContentAsByteArray, e.DocumentID);

        e.Handled = true;
    }

    private static void SaveToCustomStorage(byte[] documentContent, string p) {
        // Your custom logic to save a document to custom storage
    }
}

The example below shows how to save a document as a stream:

public static class SaveHelper {
    public static void OnSaving(object source, DevExpress.Web.Office.DocumentSavingEventArgs e) {

        var spreadsheet = (ASPxSpreadsheet)source;

        // Get the document content to be saved as a stream
        using (MemoryStream documentContentAsStream = new MemoryStream()) {
            spreadsheet.SaveCopy(documentContentAsStream, DocumentFormat.Xlsx);
            SaveToCustomStorage(documentContentAsStream, e.DocumentID);
        }

        e.Handled = true;
    }

    private static void SaveToCustomStorage(MemoryStream ms, string p) {
        // Your custom logic to save a document to custom storage
    }
}

If a custom save procedure is required, but is not provided (or e.Handled is not set to true), the save operation may try to proceed and finish with an exception.

NOTE

You should declare the Saving event handler as a globally available static method. This handler can be used by the Auto-Saving feature if it is enabled for an office control.

See the following examples on how to save and load documents from a database to learn more.

Resolving Save Operation Conflicts

The Saving event can also be used to resolve multi-user conflicts during save operations. Conflicts may arise when an end user uses the SaveAs UI command (or the SaveCopy method overload is used in code) to replace an open document with the office control's active document. The conflict occurs when the target document is already opened by DocumentManager and contains unsaved changes made by another user.

The Save event's argument exposes the MultiUserConflict property (DocumentSavingEventArgs.MultiUserConflict), which identifies the reason for the conflict. The property can have the following values:

You can resolve the issue by setting the MultiUserConflictResolve property (DocumentSavingEventArgs.MultiUserConflictResolve) to one of the following values.

  • MultiUserConflictResolve.Override

    Specifies that the target open document should be overridden with the currently processed document.

  • MultiUserConflictResolve.Persist

    Specifies that the target open document should be persisted. A specific exception will be thrown for the processed document: "It is impossible to save to an already opened file."

The code example below prevents document override:

public static class SaveHelper {
    public static void OnSaving(object source, DevExpress.Web.Office.DocumentSavingEventArgs e) {
        if(e.MultiUserConflict == DevExpress.Web.Office.MultiUserConflict.OtherUserDocumentOverride)
            e.MultiUserConflictResolve = DevExpress.Web.Office.MultiUserConflictResolve.Persist;

        ...

        e.Handled = true;
    }
See Also