Skip to main content
All docs
V23.2

Attach Files to Objects

  • 4 minutes to read

This lesson describes how to attach file collections to objects.

In this lesson you will do the following:

  • Add the File Attachment Module to the application.
  • Implement new entity classes: Resume to store a Contact’s resume information and PortfolioFileData to save file data collection items.

Note

Before you proceed, take a moment to review the previous lessons:

Step-by-Step Instructions

  1. Add the DevExpress.ExpressApp.FileAttachment.Blazor NuGet package to the MySolution.Blazor.Server project and the DevExpress.ExpressApp.FileAttachment.Win NuGet package to the MySolution.Win project. See the following topic for more information on how to install DevExpress NuGet packages: Choose Between Offline and Online DevExpress NuGet Feeds.

  2. In the MySolution.Blazor.Server project, open the Startup.cs file and add the File Attachment module to the application builder. Do the same in the Startup.cs file of the MySolution.Win project:

    public class Startup {
    // ...
        public void ConfigureServices(IServiceCollection services) {
            // ...
            services.AddXaf(Configuration, builder => {
                builder.UseApplication<MySolutionBlazorApplication>();
                builder.Modules
                     // ...
                    .AddFileAttachments();
                // ...
            });
            // ...
        }
    }
    

    If you add the File Attachment Module when you create an XAF application, the Solution Wizard generates the code that adds the File Attachment Module automatically.

  3. In the MySolution.Module\Business Objects folder, create the Resume class. Replace the generated class declaration with the following code:

    using DevExpress.ExpressApp.DC;
    using DevExpress.Persistent.Base;
    using DevExpress.Persistent.BaseImpl.EF;
    using System.Collections.ObjectModel;
    
    namespace MySolution.Module.BusinessObjects
    {
        [DefaultClassOptions]
        [ImageName("BO_Resume")]
        public class Resume : BaseObject
        {
    
            [Aggregated]
            public virtual IList<PortfolioFileData> Portfolio { get; set; } = new ObservableCollection<PortfolioFileData>();
    
            public virtual Employee Employee { get; set; }
    
            [Aggregated]
            public virtual FileData File { get; set; }
        }
    }
    
  4. Add the Resume property to the Employee class:

    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace MySolution.Module.BusinessObjects {
        [DefaultClassOptions]
        [ObjectCaptionFormat("{0:FullName}")]
        [DefaultProperty(nameof(FullName))]
        public class Employee : BaseObject {
            // ...
            public virtual IList<Resume> Resumes { get; set; } = new ObservableCollection<Resume>();
        }
        // ...
    }
    
  5. Create the PortfolioFileData class. Replace the generated class declaration with the following code:

    using DevExpress.ExpressApp.Model;
    using DevExpress.Persistent.Base;
    using DevExpress.Persistent.BaseImpl.EF;
    using DevExpress.Persistent.Validation;
    
    namespace MySolution.Module.BusinessObjects
    {
        [DefaultClassOptions]
        [ImageName("BO_FileAttachment")]
        public class PortfolioFileData : BaseObject
        {
    
            [RuleRequiredField("PortfolioFileDataRule", "Save", "File should be assigned")]
            public virtual FileData File { get; set; }
    
            public virtual Resume Resume { get; set; }
    
            public virtual DocumentType DocumentType { get; set; }
    
            public override void OnCreated()
            {
                DocumentType = DocumentType.Unknown;
            }
        }
        public enum DocumentType
        {
            SourceCode = 1,
            Tests = 2,
            Documentation = 3,
            Diagrams = 4,
            Screenshots = 5,
            Unknown = 6
        }
    }
    
  6. Add the Required attribute to the Resume property in the PortfolioFileData class.

    // ...
    namespace MySolution.Module.BusinessObjects;
    
    [DefaultClassOptions]
    [ImageName("BO_FileAttachment")]
    public class PortfolioFileData : BaseObject {   
        //...
        [Required]
        public virtual Resume Resume { get; set; }
        //...
    }
    

    The Resume and PortfolioFileData entities are connected with a One-to-Many relationship. For more information on how to create such relationships between entities, refer to the following lesson: Configure a One-to-Many Relationship.

    In the EF Core-based application, a deletion of a master object does not delete the related objects. In this lesson, we use the Required attribute to configure the associations between classes. This way you can delete the referenced objects with the master object and avoid integrity violation.

    Alternatively, you can use the Fluent API and specify the OnDelete method for the Portfolio-Resume relationship as described in the following topic: The Fluent API OnDelete Method.

  7. Open the MySolution.Module.BusinessObjects\MySolutionDbContext.cs file and add the properties of Resume and PortfolioFileData types to DbContext:

    public class MySolutionEFCoreDbContext : DbContext {
        //...
        public DbSet<Resume> Resumes { get; set; }
        public DbSet<PortfolioFileData> FileAttachments { get; set; }
    }
    
  8. Add a migration and update the database. See the following section for details: Use a DBMS: Setup Migrations.

  9. Run the application. Open the Resume List View and create a new Resume object. Fill the Employee field and add a new Portfolio File Data object. In the Portfolio File Data window, select the file that you wish to attach.

    ASP.NET Core Blazor
    ASP.NET Core Blazor Add a Resume object
    Windows Forms
    Windows Forms Add a Resume object

Users can click the file link to download the resume file.

To get a file stored within a PortfolioFileData object in code, use the SaveToStream(Stream) method of its File property.

Next Lesson

Create and Preview a Report