Skip to main content
All docs
V22.1

Save a Document

  • 7 minutes to read

Call the Save() method to initiate a save operation for the active document. The method invokes the Saving event, which allows you to implement custom saving logic. If you do not handle the event (the e.Handled property is not set to true), the control processes the document in the following ways:

  • If a document is opened from the server’s local file system, the control overwrites the original document file.
  • If a document is new (DocumentId is not specified), or a document was opened from a custom document storage, the control throws an exception. Handle the Saving event to implement custom saving logic.
  • If the save operation causes a conflict, the control throws an exception. Handle the Saving event to resolve conflicts.

Custom Save

Handle the Saving event to save a document in a custom manner. The event fires when you call the Save() method or when a user clicks the Save or SaveAs ribbon command.

A custom implementation is required when ASPxRichEdit does not have enough information to complete the document save operation automatically. Such situations occur when the control is about to save a new document or a document opened from a custom document storage by the Open(String, DocumentFormat, Func<Stream>) or Open(String, DocumentFormat, Func<Byte[]>) method.

The event argument’s e.DocumentID property identifies the document to be saved. Implement custom logic and set the e.Handled property to true to disable the built-in save routine. If it is disabled but the handler includes no custom save procedure implementation, the save operation throws an exception.

Save a Document to a Byte Array

using DevExpress.Web.Office;

protected void ASPxRichEdit1_Saving(object source, DocumentSavingEventArgs e) {
    byte[] documentContentAsByteArray = ASPxRichEdit1.SaveCopy(DocumentFormat.Rtf);
    // Implement your custom logic to save a document to a custom storage
    e.Handled = true;
}

Save a Document to a Stream

using DevExpress.Web.Office;

protected void ASPxRichEdit1_Saving(object source, DocumentSavingEventArgs e) {
    using (MemoryStream documentContentAsStream = new MemoryStream()) {
        ASPxRichEdit1.SaveCopy(documentContentAsStream, DocumentFormat.Rtf);
        // Your custom logic to save a document to a custom storage
    }       
    e.Handled = true;
}

You can declare the Saving event handler as a globally available static method to be able to use it with the autosave feature.

Resolve Save Operation Conflicts

Save operation conflicts may arise when a user calls the SaveAs UI command to replace another document that is already opened by DocumentManager and contains unsaved changes made by another user.

Handle the Saving event to resolve multi-user conflicts during save operations. The event argument exposes the following properties:

MultiUserConflict
Identifies the conflict’s reason.
MultiUserConflictResolve
Specifies how to resolve the conflict.

The code sample below prevents a document override:

using DevExpress.Web.Office;
//...
public static void OnSaving(object source, DocumentSavingEventArgs e) {
    if (e.MultiUserConflict == MultiUserConflict.OtherUserDocumentOverride)
        e.MultiUserConflictResolve = MultiUserConflictResolve.Persist;
    e.Handled = true;
}

Save a Document Copy

Call the following methods to save a copy of the active document to a file system, stream, or byte array:

  • SaveCopy(String)

    ASPxRichEdit1.SaveCopy(documentPath);
    
  • SaveCopy(Stream, DocumentFormat)

    using DevExpress.Web.Office;
    
    using (MemoryStream documentContentAsStream = new MemoryStream()) {
        ASPxRichEdit1.SaveCopy(documentContentAsStream, DocumentFormat.Rtf);
        // Your custom logic to save a document to a custom storage
    }  
    
  • SaveCopy(DocumentFormat)

    using DevExpress.Web.Office;
    
    byte[] documentContentAsByteArray = ASPxRichEdit1.SaveCopy(DocumentFormat.Rtf);
    // Your custom logic to save a document to a custom storage
    

These methods export the document with the current changes, but do not affect the original document.

Autosave

Set the AutoSaveMode property to On to make the ASPxRichEdit control save the active document automatically on each timeout specified by the AutoSaveTimeout property. Note, to improve control performance, the DocumentManager processes multiple documents in parts with a 20-second interval. This behavior can cause a difference between the specified and the actual autosave timeout. For instance, when the specified timeout is short and the document manager processes a lot of documents, the actual timeout duration can increase.

If a document is opened by multiple ASPxRichEdit controls with the autosave feature enabled, the timeout is set to the smallest value among all these controls.

<dx:ASPxRichEdit ID="ASPxRichEdit1" runat="server" WorkDirectory="~/App_Data/WorkDirectory" 
    AutoSaveMode="On" AutoSaveTimeout="00:10:00" >
</dx:ASPxRichEdit>

The autosave feature invokes the AutoSaving event that allows you to implement custom autosave logic. If you do not handle the event (the e.Handled property is set to false), the control processes the document in the following ways:

  • If a document is opened from the server’s local file system, the control overwrites the original document file.
  • If a document is new, or a document was opened from a custom document storage, the control throws an exception. Handle the AutoSaving event to implement custom saving logic.

Custom Autosave

Handle the AutoSaving event to process custom save operations triggered by the autosave timer (AutoSaveTimeout).

A custom implementation is required under the same circumstances as the custom save functionality. We strongly recommend that you declare this event handler as a globally available static method and assign it to both the AutoSaving and Saving events.

The following code sample assigns a handler to the AutoSaving event in the global.asax file’s Application_Start method.

Save a Document to a Byte Array

using DevExpress.Web.Office;

void Application_Start(object sender, EventArgs e) {
     DocumentManager.AutoSaving += DocumentManager_AutoSaving;
}
static void DocumentManager_AutoSaving(IDocumentInfo documentInfo, DocumentSavingEventArgs e) {
    RichEditDocumentInfo info = documentInfo as RichEditDocumentInfo;
    byte[] documentContentAsByteArray = info.SaveCopy(DocumentFormat.Rtf);
    SaveHelper.SaveToCustomStorage(documentContentAsByteArray, e.DocumentID);
    e.Handled = true; 
}
using DevExpress.Web.Office;

public static class SaveHelper {
    private static void SaveToCustomStorage(byte[] documentContent, string p) {
        // Your custom logic to save a document to a custom storage
    }
}
protected void ASPxRichEdit1_Saving(object source, DocumentSavingEventArgs e) {
    byte[] documentContentAsByteArray = ASPxRichEdit1.SaveCopy(DocumentFormat.Rtf);
    SaveHelper.SaveToCustomStorage(documentContentAsByteArray, e.DocumentID);      
    e.Handled = true;
}

Save a Document to a Stream

using DevExpress.Web.Office;

void Application_Start(object sender, EventArgs e) {
     DocumentManager.AutoSaving += DocumentManager_AutoSaving;
}

static void DocumentManager_AutoSaving(IDocumentInfo documentInfo, DocumentSavingEventArgs e) {
    RichEditDocumentInfo info = documentInfo as RichEditDocumentInfo;
    using (MemoryStream documentContentAsStream = new MemoryStream()) {
        info.SaveCopy(documentContentAsStream, DocumentFormat.Rtf);
        SaveHelper.SaveToCustomStorage(documentContentAsStream, e.DocumentID);
    }
    e.Handled = true; 
}
using DevExpress.Web.Office;

public static class SaveHelper {
    private static void SaveToCustomStorage(MemoryStream ms, string p) {
        // Your custom logic to save a document to a custom storage
    }
}
protected void ASPxRichEdit1_Saving(object source, DocumentSavingEventArgs e) {
    using (MemoryStream documentContentAsStream = new MemoryStream()) {
        ASPxRichEdit1.SaveCopy(documentContentAsStream, DocumentFormat.Rtf);
        SaveHelper.SaveToCustomStorage(documentContentAsStream, e.DocumentID);
    }       
    e.Handled = true;
}