Zum Ende der Metadaten springen
Zum Anfang der Metadaten

Sie zeigen eine alte Version dieser Seite an. Zeigen Sie die aktuelle Version an.

Unterschiede anzeigen Seitenhistorie anzeigen

« Vorherige Version anzeigen Version 9 Nächste Version anzeigen »

Beschreibung

Mit Einstellungen des Interface "IWmsActivitySettingList" kann der WMS-Benutzer mehrere Einstellungen des selben Typs hinterlegen. Über Zuordnungen kann er einzelne dieser Einstellungen dann im Workflow und in Aktivitäten verwenrden.

Die Einstellungen SMTP, FTP und Datenbanken im WMS nutzen dieses Interface. 

Häufige Anwendungsfälle:

  • Allgemeingültige Verbindungseinstellungen zu Drittsystemen oder Geräten

Inhalt


Aufbau des Interface IWmsActivitySettingList

Eigenschaft / Methode

Beschreibung

Identifier

Immer gleicher, eindeutiger Identifier dieser Einstellung!

Title

Titel der Einstellung, wird als Name des Menüs verwendet.

TitleToolTip

Tooltip für das Menü bzw. die Schaltfläche.

DialogContent

UserControl zur Bearbeitung der Einstellung im Dialog.
Erst in InitialiseDialog-Methoden zusammen bauen!

IsValidDialogData()

Prüft, ob die Eingaben im Dialog valide sind. Nur dann wird der Dialog geschlossen.

AddErrorToDialog(string error)

Diese Methode soll die angegbene Fehlermeldung im Dialog anzeigen.
Das WMS ruft diese Methode auf, wenn eine Einstellung mit diesem Namen bereits vorhanden ist.

InitialiseDialogData(WmsSettingEntry entry)

Erzeugt die Oberfläche zur Bearbeitung eines Eintrages.

GetDialogData()

Ermittelt die Eingaben aus dem Dialog um sie zu speichern.

Beispiel 

Im Folgenden entwickeln wir eine Aktivität, um Dateien auf einen FTP Server hochzuladen. Der WMS-Benutzer kann beliebig viele FTP-Einstellungen konfigurieren und über die Zuordnungen die

Implementierung IWmsActivitySettingList

IWmsActivitySettingList
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Controls;
using Accantum.Wms.ActivityContracts.Settings;
using ActivitySample.Activities.FtpUpload.V01;

namespace ActivitySample.Activities.FtpUpload.Setting
{
    public class FtpConfigurationSettings :  IWmsActivitySettingList
    {
        public static Guid SettingId = new Guid("1f2d1198-b5c7-47f9-a8c4-fda02cc49d61");

        // Eindeutiger Identifier dieser Einstellung
        public Guid Identifier => SettingId;

        /// <summary>
        /// Bezeichnung für das Einstellungsmenü
        /// </summary>
        public string Title => "FTP";

        /// <summary>
        /// Tooltip für die Schaltfläche im Einstellungsmenü
        /// </summary>
        public string TitleTooltip => "FTP-Verbindungen verwalten, die in den FTP-Aktivitäten zur Verfügung stehen.";

        /// <summary>
        /// Prefix für Zuordnungsvariablen
        /// </summary>
        public string MappingVariablePrefix => "ftp";

        /// <summary>
        /// Zusätzliche Spalten, die in der Übersicht angezeigt werden sollen
        /// </summary>
        public IEnumerable<WmsSettingColumnDef> ColumnDefinitions => new List<WmsSettingColumnDef>
        {
            new WmsSettingColumnDef("FTP-Host", nameof(WmsFtpConfig.Host)),
            new WmsSettingColumnDef("Verzeichnis", nameof(WmsFtpConfig.RootDirectory))
        };

        /// <summary>
        /// UserControl zur Bearbeitung der Einstellung im Dialog.
        /// </summary>
        public UserControl DialogContent { get; private set; }

        /// <summary>
        /// Prüft, ob die Eingaben im Dialog valide sind. Nur dann wird der Dialog geschlossen
        /// </summary>
        /// <returns>true, wenn der Dialog geschlossen werden darf</returns>
        public Task<bool> IsValidDialogData()
        {
            var oViewModel = (DialogContent as FtpConfig)?.ViewModel;
            return Task.FromResult(oViewModel != null && oViewModel.IsValid());
        }

        /// <summary>
        /// Zeigt eine Fehlermeldung im Dialog an.
        /// </summary>
        /// <param name="a_sPropertyName">Name der fehlerhaften Eigenschaft</param>
        /// <param name="a_sErrorMessage">Fehlermeldung</param>
        public void AddErrorToDialog(string a_sPropertyName, string a_sErrorMessage)
        {
            var oViewModel = (DialogContent as FtpConfig)?.ViewModel;
            oViewModel?.AddErrorToDialog(a_sPropertyName, a_sErrorMessage);
        }

        /// <summary>
        /// Erzeugt die Oberfläche zur Bearbeitung eines Eintrages
        /// </summary>
        /// <param name="a_oSettingEntry"></param>
        public void InitialiseDialogData(WmsSettingEntry a_oSettingEntry)
        {
            var oVm = new FtpConfigViewModel(a_oSettingEntry);
            DialogContent = new FtpConfig(oVm);
        }

        /// <summary>
        /// Ermittelt die Eingaben aus dem Dialog um sie zu speichern
        /// </summary>
        /// <returns></returns>
        public WmsSettingEntry GetDialogData()
        {
            var oViewModel = (DialogContent as FtpConfig)?.ViewModel;
            return oViewModel?.GetSettingEntry();
        }
    }
}


WmsFtpConfig: Wert der FTP Einstellung, die gespeichert wird
using System;
using System.Security.Authentication;
using System.Xml.Serialization;
using Accantum.Wms.ActivityContracts.Settings;

namespace ActivitySample.Activities.FtpUpload.V01
{
    /// <summary>
    /// Einstellungen zu einem FTP-Account
    /// </summary>
    [Serializable]
    public class WmsFtpConfig
    {
        private readonly WmsSettingEntry m_oSettingEntry;
        private string m_strRootDirectory;

        public WmsFtpConfig()
        {
            Port = null;
        }

        public WmsFtpConfig(WmsSettingEntry a_oSettingEntry)
        {
            m_oSettingEntry = a_oSettingEntry;
            Id = a_oSettingEntry.Id;
            Name = a_oSettingEntry.Name;

            //Eigenschaften aus dem Properites-Array laden
            Host = a_oSettingEntry.Properties[nameof(Host)] as string;
            Port = a_oSettingEntry.Properties[nameof(Port)] as int?;
            User = a_oSettingEntry.Properties[nameof(User)] as string;
            EncryptedPassword = a_oSettingEntry.Properties[nameof(EncryptedPassword)] as string;
            EncryptionMode = a_oSettingEntry.Properties[nameof(EncryptionMode)] as EFtpEncryptionMode? ?? EFtpEncryptionMode.AutoDetect;
            EncryptionProtocol = a_oSettingEntry.Properties[nameof(EncryptionProtocol)] as SslProtocols? ?? SslProtocols.None;

            RootDirectory = a_oSettingEntry.Properties[nameof(RootDirectory)] as string;
        }

        /// <summary>
        /// Eindeutige Id aus der Einstellung
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// Name aus der Einstellung
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// FTP-Host für den Datenaustausch
        /// </summary>
        public string Host { get; set; }

        /// <summary>
        /// Port, welcher für den FTP-Zugang verwendet wird. Wenn nicht gesetzt, dann werden die Standardports verwendet
        /// Standardwert: null
        /// </summary>
        public int? Port { get; set; }

        /// <summary>
        /// Benutzer des FTP-Zugangs.
        /// </summary>
        public string User { get; set; }

        /// <summary>
        /// Passwort des FTP-Zugangs
        /// </summary>
        [XmlElement("Password")]
        public string EncryptedPassword { get; set; }

        /// <summary>
        /// Modus der Verschlüsselung (none, explizit, implizit).
        /// </summary>
        public EFtpEncryptionMode EncryptionMode { get; set; }

        /// <summary>
        /// Protokoll der Verschlüsselung (SSL -Secure Sockets Layer, TLS).
        /// </summary>
        public SslProtocols EncryptionProtocol { get; set; }

        /// <summary>
        /// Basis-Verzeichnis auf dem FTP-Server (Verzeichnisse mit "/" getrennt, nicht mit "\")
        /// </summary>
        public string RootDirectory
        {
            get => m_strRootDirectory;
            set
            {
                if (value != null)
                {
                    string strPath = value.Replace('\\', '/');
                    m_strRootDirectory = (string.IsNullOrEmpty(strPath) || strPath.StartsWith("/")) ? strPath : $"/{strPath}";
                }
                else
                {
                    m_strRootDirectory = null;
                }
            }
        }

        /// <summary>
        /// Um Einstellung zu speichern in ein WmsSettingEntry wandeln und die zu speichernden Eigenschaften in das Properties-Array schreiben
        /// </summary>
        public WmsSettingEntry ToWmsSettingEntry()
        {
            return new WmsSettingEntry
            {
                Id = m_oSettingEntry.Id,
                Name = m_oSettingEntry.Name,
                Description = m_oSettingEntry.Description,
                CreationDate = m_oSettingEntry.CreationDate,
                CreationUser = m_oSettingEntry.CreationUser,
                ModifyDate = m_oSettingEntry.ModifyDate,
                ModifyUser = m_oSettingEntry.ModifyUser,
                Properties = new WmsPropertyCollection
                {
                    new WmsSettingEntryProperty(nameof(Host), Host),
                    new WmsSettingEntryProperty(nameof(Port), Port),
                    new WmsSettingEntryProperty(nameof(User), User),
                    new WmsSettingEntryProperty(nameof(EncryptedPassword), EncryptedPassword),
                    new WmsSettingEntryProperty(nameof(EncryptionMode), EncryptionMode),
                    new WmsSettingEntryProperty(nameof(EncryptionProtocol), EncryptionProtocol),
                    new WmsSettingEntryProperty(nameof(RootDirectory), RootDirectory)
                }
            };
        }
    }
}


Implementierung der Oberfläche zur Eingabe der Einstellung

ViewModel des FTP-Dialogs
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Security;
using System.Security.Authentication;
using Accantum.Wms.ActivityContracts.Settings;
using ActivitySample.Activities.FtpUpload.V01;
using ActivitySample.Helper;
using ActivitySample.Properties;

namespace ActivitySample.Activities.FtpUpload.Setting
{
    public class FtpConfigViewModel : ValidatableModelBase
    {
        private string m_sName;
        private string m_sDescription;
        private string m_sHost;
        private string m_sUsername;
        private SecureString m_sPassword;
        private int? m_iPort;
        private EFtpEncryptionMode m_eEncryptionMode;
        private SslProtocols m_eEncryptionProtocol;
        private string m_sRootDirectory;
        private bool m_bIsBusy;
        private string m_sConnectionStateInfo;

        private readonly WmsSettingEntry m_oSettingEntry;

        public FtpConfigViewModel(WmsSettingEntry a_oSettingEntry)
        {
            m_oSettingEntry = a_oSettingEntry ?? new WmsSettingEntry();
            SetProperties();
        }

        #region Properties

        [Required]
        public string Name
        {
            get => m_sName;
            set => SetProperty(ref m_sName, value);
        }

        public string Description
        {
            get => m_sDescription;
            set => SetProperty(ref m_sDescription, value);
        }

        [Required, Display(ResourceType = typeof(Resource), Name = "Host")]
        public string Host
        {
            get => m_sHost;
            set => SetProperty(ref m_sHost, value);
        }

        [Display(ResourceType = typeof(Resource), Name = "Username")]
        public string Username
        {
            get => m_sUsername;
            set => SetProperty(ref m_sUsername, value);
        }

        public SecureString Password
        {
            get => m_sPassword;
            set => SetProperty(ref m_sPassword, value);
        }

        public int? Port
        {
            get => m_iPort;
            set => SetProperty(ref m_iPort, value);
        }

        public EFtpEncryptionMode EncryptionMode
        {
            get => m_eEncryptionMode;
            set
            {
                SetProperty(ref m_eEncryptionMode, value);
                if (value == EFtpEncryptionMode.AutoDetect)
                    EncryptionProtocol = SslProtocols.None;
            }
        }

        public SslProtocols EncryptionProtocol
        {
            get => m_eEncryptionProtocol;
            set => SetProperty(ref m_eEncryptionProtocol, value);
        }

        [Display(ResourceType = typeof(Resource), Name = "RootDirectoryName")]
        public string RootDirectory
        {
            get => m_sRootDirectory;
            set => SetProperty(ref m_sRootDirectory, value);
        }
        

        public bool IsBusy
        {
            get => m_bIsBusy;
            set => SetPropertyWithoutValidate(ref m_bIsBusy, value);
        }

        public string ConnectionStateInfo
        {
            get => m_sConnectionStateInfo;
            set => SetPropertyWithoutValidate(ref m_sConnectionStateInfo, value);
        }

        #endregion


        public bool IsValid()
        {
            return ValidateObject();
        }

        public void AddErrorToDialog(string a_sPropertyName, string a_sErrorMessage)
        {
            AddError(a_sPropertyName, a_sErrorMessage);
        }
        
        public WmsFtpConfig CreateFtpConfig()
        {
            m_oSettingEntry.Name = Name;
            m_oSettingEntry.Description = Description;

            var sPasswortString = new NetworkCredential(string.Empty, Password).Password;

            var oConfig = new WmsFtpConfig(m_oSettingEntry)
            {
                Host = Host,
                Port = Port,
                User = Username,
                EncryptedPassword = sPasswortString, //Hier Verschlüsseln! z.B. TripleDES
                EncryptionMode = EncryptionMode,
                EncryptionProtocol = EncryptionProtocol,
                RootDirectory = RootDirectory
            };
            return oConfig;
        }

        public WmsSettingEntry GetSettingEntry()
        {
            var oFtpConfig = CreateFtpConfig();
            return oFtpConfig.ToWmsSettingEntry();
        }

        
        private void SetProperties()
        {
            var oFtp = new WmsFtpConfig(m_oSettingEntry);
            m_sName = m_oSettingEntry.Name;
            m_sDescription = m_oSettingEntry.Description;

            var oSecurePassword = new NetworkCredential(string.Empty, oFtp.EncryptedPassword).SecurePassword; //Hier Entschlüsseln

            m_sHost = oFtp.Host;
            m_sUsername = oFtp.User;
            m_sPassword = oSecurePassword;
            m_iPort = oFtp.Port;
            m_eEncryptionMode = oFtp.EncryptionMode;
            m_eEncryptionProtocol = oFtp.EncryptionProtocol;
            m_sRootDirectory = oFtp.RootDirectory;
        }
    }
}


Oberfläche zur Eingabe der FTP-Einstellung
<UserControl x:Class="ActivitySample.Activities.FtpUpload.Setting.FtpConfig"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:enums="clr-namespace:ActivitySample.Activities.FtpUpload.V01"
             xmlns:settings="clr-namespace:ActivitySample.Activities.FtpUpload.Setting"
             xmlns:helper="clr-namespace:ActivitySample.Helper"
             xmlns:resx="clr-namespace:ActivitySample.Properties"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="500"
             d:DataContext="{d:DesignInstance {x:Type settings:FtpConfigViewModel}}">
    <UserControl.Resources>
        <ResourceDictionary>
            <helper:InvertedBooleanConverter x:Key="InvertedBooleanConverter"/>

            <Style x:Key="TextareaStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
                <Style.Setters>
                    <Setter Property="AcceptsTab" Value="False" />
                    <Setter Property="AcceptsReturn" Value="True" />
                    <Setter Property="TextWrapping" Value="Wrap" />
                    <Setter Property="SpellCheck.IsEnabled" Value="True" />
                    <Setter Property="VerticalContentAlignment" Value="Top" />
                    <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
                </Style.Setters>
            </Style>
        </ResourceDictionary>
    </UserControl.Resources>

    <Grid Margin="2" IsEnabled="{Binding ElementName=BusyIndicator, Path=IsBusy, Converter={StaticResource InvertedBooleanConverter}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*" MinWidth="300" MaxWidth="500"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="{x:Static resx:Resource.Name}"/>
        <!--UpdateSourceTrigger ist nötig, um gleich bei Änderungen Speichern-Button zu aktivieren-->
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="1" Grid.Column="0" Content="{x:Static resx:Resource.Description}"/>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Description, UpdateSourceTrigger=PropertyChanged}"
                 Style="{StaticResource TextareaStyle}" MinLines="2" MaxLines="4"/>

        <Label Grid.Row="2" Grid.Column="0" Content="{x:Static resx:Resource.Host}"/>
        <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Host, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="3" Grid.Column="0" Content="{x:Static resx:Resource.Port}"/>
        <!--Hier ist auch ein Control denkbar, (das WMS nutzt Controls von Telerik) telerik:RadNumericUpDown-->
        <TextBox Grid.Row="3" Grid.Column="1" Width="80" HorizontalAlignment="Left" Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="4" Grid.Column="0" Content="{x:Static resx:Resource.Username}"/>
        <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="5" Grid.Column="0" Content="{x:Static resx:Resource.Password}"/>
        <PasswordBox Grid.Row="5" Grid.Column="1" x:Name="PasswordBox"></PasswordBox>

        <Label Grid.Column="0" Grid.Row="6" Content="{x:Static resx:Resource.Ftp_EncryptionMode}" ToolTip="{x:Static resx:Resource.Ftp_EncryptionModeDesc}"/>
        <ComboBox Grid.Column="1" Grid.Row="6"
                  SelectedValue="{Binding EncryptionMode}"
                  ItemsSource="{Binding Source={helper:EnumToItemsSource {x:Type enums:EFtpEncryptionMode}}}"
                  DisplayMemberPath="DisplayName" SelectedValuePath="Value" />


        <Label Grid.Row="7" Grid.Column="0" Content="{x:Static resx:Resource.RootDirectoryName}"/>
        <TextBox Grid.Row="7" Grid.Column="1" Text="{Binding RootDirectory, UpdateSourceTrigger=PropertyChanged}"/>
        
    </Grid>
</UserControl>


Beispiel Setting Control - CodeBehind (xaml.cs)
using System.Net;
using System.Windows.Controls;

namespace ActivitySample.Activities.FtpUpload.Setting
{
    /// <summary>
    /// Interaction logic for FtpSettings.xaml
    /// </summary>
    public partial class FtpConfig: UserControl
    {
        public FtpConfig(FtpConfigViewModel a_oViewModel)
        {
            InitializeComponent();
            DataContext = a_oViewModel;
            PasswordBox.Password = new NetworkCredential(string.Empty, a_oViewModel.Password).Password;
        }

        public FtpConfigViewModel ViewModel => DataContext as FtpConfigViewModel;
    }
}

Verwendung in der Aktivität

Beispiel zur Verwendung in der Aktivität
using System;
using System.Activities;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Authentication;
using Accantum.Wms.ActivityContracts;
using Accantum.Wms.ActivityContracts.Attributes;
using Accantum.Wms.ActivityContracts.Settings;
using ActivitySample.Activities.FtpUpload.Setting;
using ActivitySample.Images;
using ActivitySample.Properties;

namespace ActivitySample.Activities.FtpUpload.V01
{
    /// <summary>
    /// Mit dieser Aktivität kann eine Datei auf einen FTP-Server hochgeladen werden.
    /// BEISPIEL für eine Aktivität mit mehreren Einstellungen (<see cref="IWmsActivitySettingList"/>
    /// </summary>
    [Designer(typeof(FtpUploadDesigner))]
    [ActivitySettingsType(typeof(FtpConfigurationSettings))]
    public sealed class FtpUploadActivity : CodeActivity
    {
        public FtpUploadActivity()
        {
            DisplayName = Resource.FtpUpload_DisplayName;
            CreateTargetDir = true;
        }

        /// <summary>
        /// Id der Konfiguration des FTP-Server-Zugangs (aus einer Zuordnung)
        /// </summary>
        [LocalizedDisplayName("Ftp_FtpConfig", typeof(Resource))]
        [LocalizedDescription("Ftp_FtpConfigDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Setting", typeof(Resource))]
        [ExcludeInAnnotation]
        public InArgument<Guid> FtpConfig { get; set; }

        /// <summary>
        /// Verzeichnis der Quelldatei
        /// </summary>
        [LocalizedDisplayName("SourceDirectory", typeof(Resource))]
        [LocalizedDescription("SourceDirectoryDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))]
        public InArgument<string> SourceDirectory { get; set; }

        /// <summary>
        /// Name der Quelldatei 
        /// </summary>
        [LocalizedDisplayName("SourceFilename", typeof(Resource))]
        [LocalizedDescription("SourceFilenameDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))]
        public InArgument<string> SourceFilename { get; set; }

        /// <summary>
        /// FTP-Verzeichnis in welches die Datei hochgeladen wird
        /// </summary>
        [LocalizedDisplayName("Ftp_FtpDirectory", typeof(Resource))]
        [LocalizedDescription("FtpUpload_FtpDirectoryDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))]
        public InArgument<string> FtpDirectory { get; set; }

        /// <summary>
        /// Kennzeichen, ob die Verzeichnisstrukur der Zieldatei angelegt werden soll,
        /// wenn diese nicht existiert.
        /// </summary>
        [LocalizedDisplayName("CreateTargetDir", typeof(Resource))]
        [LocalizedDescription("CreateTargetDirDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))]
        public bool CreateTargetDir { get; set; }

        /// <summary>
        /// Kennzeichen, ob eine bereits existierende Zieldatei überschrieben werden soll.
        /// </summary>
        [DefaultValue(false)]
        [LocalizedDisplayName("OverrideExistingFile", typeof(Resource))]
        [LocalizedDescription("OverrideExistingFileDesc", typeof(Resource))]
        [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))]
        public bool OverrideExistingFile { get; set; }


        protected override void CacheMetadata(CodeActivityMetadata a_oMetadata)
        {
            if (FtpConfig?.Expression == null)
                a_oMetadata.AddValidationError(Resource.Ftp_FtpConfig);
            if (SourceFilename?.Expression == null)
                a_oMetadata.AddValidationError(Resource.SourceFilename);
            if (SourceDirectory?.Expression == null)
                a_oMetadata.AddValidationError(Resource.SourceDirectory);

            base.CacheMetadata(a_oMetadata);
        }

        protected override void Execute(CodeActivityContext a_oContext)
        {
            WmsFtpConfig oFtpConfig = ResolveFptConfig(a_oContext, FtpConfig?.Get(a_oContext));

            string sDirectory = SourceDirectory.Get(a_oContext);
            string sFileName = SourceFilename.Get(a_oContext);

            //Hochzuladende Datei prüfen
            FileInfo oSourceFile = new FileInfo(Path.Combine(sDirectory, sFileName));
            CheckFileInfo(a_oContext, oSourceFile);

            string strFtpDirectory = FtpDirectory.Get(a_oContext);

            using (WmsFtpClient oFtpClient = new WmsFtpClient(oFtpConfig))
            {
                if (!oFtpClient.UploadFile(oSourceFile, strFtpDirectory, CreateTargetDir, OverrideExistingFile))
                    throw new Exception($"FTP-Server: Fehler bei Hochladen der Datei.{Environment.NewLine}{oFtpClient.LastError}");
            }
        }


        /// <summary>
        /// Prüft, ob die Datei existiert und ob der Mandant darauf zugreifen darf.
        /// </summary>
        /// <param name="a_oContext"></param>
        /// <param name="a_oFileInfo"></param>
        private void CheckFileInfo(CodeActivityContext a_oContext, FileInfo a_oFileInfo)
        {
            if (string.IsNullOrEmpty(a_oFileInfo.FullName))
                throw new Exception("Es wurde kein Dateiname angegeben.");

            // Prüfen, ob die  Datei in einem gültigen Mandantenverzeichnis liegt
            var oWmsApi = a_oContext.GetExtension<IWmsApiExtension>();
            if (!oWmsApi.IsInTenantFolder(a_oFileInfo, a_oContext))
                throw new AuthenticationException("Auf das angegebene Verzeichnis darf nicht zugegriffen werden.");


            if (!a_oFileInfo.Exists)
                throw new Exception($"Die Datei {a_oFileInfo.FullName} existiert nicht.");
        }

        /// <summary>
        /// FTP-Einstellung ermitteln
        /// </summary>
        public static WmsFtpConfig ResolveFptConfig(ActivityContext a_oContext, Guid? a_gSettingEntryId)
        {
            //Einstellung aus dem ActivityContext ermitteln, dazu ist der Identifier des Settings notwendig
            WmsSettingsCollection oExtension = a_oContext.GetExtension<WmsSettingsCollection>();
            //In den SettingEntries suchen, ob ein Eintrag mit der Id vorhanden ist.
            WmsSettingEntry oSettingEntry = oExtension[FtpConfigurationSettings.SettingId]?.SettingEntries?.FirstOrDefault(s => s.Id == a_gSettingEntryId);

            if (oSettingEntry == null)
                throw new Exception($"Einstellung mit Id {a_gSettingEntryId} ist nicht vorhanden!");
            
            return new WmsFtpConfig(oSettingEntry);
        }
    }
}


Designer zur FTP Aktivität
<sap:ActivityDesigner x:Class="ActivitySample.Activities.FtpUpload.V01.FtpUploadDesigner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
    xmlns:converters="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    xmlns:resx="clr-namespace:ActivitySample.Properties"
    xmlns:v01="clr-namespace:ActivitySample.Activities.FtpUpload.V01"
    xmlns:theme="clr-namespace:Accantum.Wms.ActivityContracts.Theme;assembly=WmsActivityContracts">

    <sap:ActivityDesigner.Resources>
        <converters:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />

        <DataTemplate x:Key="ExpandedTemplate" DataType="v01:FtpUploadDesigner">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <Label Grid.Column="0" Grid.Row="0" Content="{x:Static resx:Resource.Ftp_FtpConfig}" 
                       ToolTip="{x:Static resx:Resource.Ftp_FtpConfigDesc}"/>
                <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="0"
                                        OwnerActivity="{Binding ModelItem}"
                                        Expression="{Binding Path=ModelItem.FtpConfig, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
                                        ExpressionType="system:Guid"/>

                <Label Grid.Column="0" Grid.Row="1" Content="{x:Static resx:Resource.SourceDirectory}" 
                       ToolTip="{x:Static resx:Resource.SourceDirectoryDesc}"/>
                <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="1"
                                        OwnerActivity="{Binding ModelItem}"
                                        Expression="{Binding Path=ModelItem.SourceDirectory, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
                                        ExpressionType="system:String"/>

                <Label Grid.Column="0" Grid.Row="2" Content="{x:Static resx:Resource.SourceFilename}" 
                       ToolTip="{x:Static resx:Resource.SourceFilenameDesc}"/>
                <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="2"
                                        OwnerActivity="{Binding ModelItem}"
                                        Expression="{Binding Path=ModelItem.SourceFilename, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
                                        ExpressionType="system:String"/>

                <Label Grid.Column="0" Grid.Row="3" Content="{x:Static resx:Resource.Ftp_FtpDirectory}" 
                       ToolTip="{x:Static resx:Resource.FtpUpload_FtpDirectoryDesc}"/>
                <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="3"
                                        OwnerActivity="{Binding ModelItem}"
                                        Expression="{Binding Path=ModelItem.FtpDirectory, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
                                        ExpressionType="system:String"/>

                <Label Grid.Column="0" Grid.Row="4" Content="{x:Static resx:Resource.Options}"/>
                <StackPanel Grid.Column="1" Grid.Row="4" Orientation="Horizontal">
                    <CheckBox Content="{x:Static resx:Resource.OverrideExistingFile}"
                              IsChecked="{Binding Path=ModelItem.OverrideExistingFile, Mode=TwoWay}" />
                    <CheckBox Content="{x:Static resx:Resource.CreateTargetDir}"
                              IsChecked="{Binding Path=ModelItem.CreateTargetDir, Mode=TwoWay}" />
                </StackPanel>
            </Grid>
        </DataTemplate>

        <Style x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}">
            <Setter Property="ContentTemplate" Value="{x:Static theme:WmsActivityTheme.CollapsedTemplate}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=ShowExpanded}" Value="true">
                    <Setter Property="ContentTemplate" Value="{StaticResource ExpandedTemplate}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

    </sap:ActivityDesigner.Resources>

    <ContentPresenter Style="{StaticResource ExpandOrCollapsedStyle}" Content="{Binding}"/>

</sap:ActivityDesigner>



  • Keine Stichwörter