Freitag, 21. Oktober 2016

Verwenden von third-party DLL in AX2012 C# Projekten



Wenn man in einer AX2012 C# Projekt eine third-party DLL, oder ein Nuget Package verwendet möchte. Müssen diese manuell hinzugefügte werden. AX gibt euch folgende Meldung aus, wenn das Paket nicht gefunden werden kann:


This project refers to at least one nuget package missing on this computer. enable the restoration of nuget packages to download the missing file.


Hierbei kann man wie folgt vorgehen:


1.       Ladet die third-party DLL über nuget herunter oder nutzt eine bereits bestehende DLL.


2.       Fügt die third-party DLL eurer AX Klassenbibliothek über den Solution Explorer hinzu.


3.       Klickt im Solution Explorer rechts auf euer Projekt und wählt „Ordner im Datei-Explorer öffnen“


4.       Öffnet nun die .cproj Datei mit einem Texteditor


5.       Sucht nach dem XML Tag ItemGroup und fügt die rotmarkierte ItemGroup hinzu.(MyDLL.dll mit dem Namen der von eurer third-party DLL ersetzten.



6.       Speicher die Änderungen


7.       Visual Studio fragt euch nun ob die Projektdatei neu eingelesen werden soll. Die bestätigt Ihr.


8.       Fügt nun die Änderungen dem AOT hinzu in dem Ihr über den Solution Explorer mit „Add to AOT“
Somit ist die third-party DLL nun auch für das AX bereitgestellt und kann verwendet werden

Siehe auch http://daxmusings.codecrib.com/2013/07/auto-deploying-dlls-and-other-resources.html



Freitag, 23. Oktober 2015

Spaltenüberschriftenzeile auf jeder Seite SSRS Dynamics AX 2012

Während Entwicklung von SSRS Report für Dynamics AX 2012, fand ich heraus, dass wenn Bericht über mehreren Seiten geht, Spaltenüberschrift nicht auf alle Seiten wiederholt werden.

Obwohl die Eigenschaft RepeatColumnHeaders der Tabelle auf true gesetzt wurde.

Um das Problem zu lösen muss die Eigenschaft RepeatOnNewPage für die Spaltenüberschrift gesetzt werden.

Wählt hierfür das Tablix und unterhalb der rechten Seite der Spalten Gruppenkopf, und klickt dort auf die kleine Pfeilspitze und wählt den erweiterten Modus.


Jetzt über rechten Maustaste auf klicken statische in Zeilengruppen, oder F4 drücken, um das Eigenschaften Fenster zu öffnen.

Von Eigenschaften Fenster die Eigenschaft RepeatOnNewPage auf True stellen.


Wenn Ihr den Bericht bereitstellen habt, wird die Spaltenüberschrift nun auf jeder Seite angezeigt.

Bis zum nächstem mal.....

Dienstag, 30. September 2014

Dokumenten Druck aus dem EP über SSRS Reports

Für ein Projekt war es nötig das über das Enterprise Portal ein Dokument aus dem AX 2012 erstellt wird und im Browser als neues Tab angezeigt wird.
In diesem Post werden ich nur auf die Call aus dem EP an eine AX Klasse, die die Erstellung und Ablage des Dokuments in einem Share übernimmt, sowie das Aufrufen des Dokuments aus dem EP beschreiben.
Die eigentliche Erstellung eines PDF über den SSRS können Sie dem MSDN entnehmen:

Reporting in Microsoft Dynamics AX [AX 2012]

Beginnen wir mit dem erstellen der AX Klasse EPPrintDocuments. Im Grunde hält diese Klasse nur die Statischen Methode die aus dem EP angesprochen werden:















Die Klasse liefert uns als Rückgabe wert eine Kommaseparierte Liste der Dateipfade zu den erstellten Dokumenten.

Im DynamicsAXUserControl habe ich eine Button hinterlegt der die Klasse EPPrintDocuments wie folgt aufruft:


Damit der Redirect in einem neuen Tab geöffnet wird verwende ich die Response.Redirect Extension Methode auf folgenden Projekt Response.Redirect into a new window
















welche das gewünschte verhalten per JavaScript Befehl an den Client sendet.

ich wünsche noch viel Spaß beim selber ausprobieren, bis zum nächsten mal....

Dienstag, 23. September 2014

Datenabrufe aus AX2012 R3 aus einer Windows App

Der AX2012 R3 bietet uns von hause aus schon einige Web Service mit deren Hilfe wir Daten aus dem AX konsumieren können. Hier bei möchte ich den QueryService Web Service hervorheben. Mit diesem lassen sich sowohl statische Querys aus dem AX ausführen als auch eigen Querys die in der Applikation definiert werden.

hier ein kleines Beispiel für eine AX Query Ausführung:












und nun das Beispiel für eine eigenes Query:



die im den Beispiel verwendeten Methode FetchData iteriert das zurück gelieferte XML und wandelt es in eine ObservableCollection des jeweiligen erwarteten Datentyps um.

Freitag, 22. August 2014

Enterprise Protal AX2012: Erstellen eines Table Context aus einem AxRecordAdapter

Im ersten Moment hatte ich versucht gemäß des MSDN Artikel Using Context from Code in Enterprise Portal [AX 2012] vorzugehen.

Da dies sich nicht so umsetzten lies hab ich folgende Lösung verwendet um einen Table Context zu erstellen:

Dienstag, 8. Juli 2014

Fehler bei der Datenbank Synchronisierung für AX 2012 R3


Es ist letztlich vorgekommen das die Datenbank Synchronisierung  für AX 2012 R3 fehlgeschlagen ist mit der folgender Fehlermeldung die sehr Aufschlussreich war o_O 

Ein Befehl der Datendefinitionssprache kann nicht für () ausgeführt werden.
Die SQL-Datenbank hat einen Fehler gemeldet.
Naja, für jemanden der schon länger mit AX arbeitet ist so was Aussagekräftiges nicht ungewöhnliches. Nach ein wenig suchen konnte ich auch SQL Anweisung finde die diesen Fehler verursachte. Das kuriose war nur das es sich dabei um ein View handelt deren Konfigurationsschlüsse deaktiviert sind.

SQL-Anweisung: ALTER TABLE TAXINTGREXPORTDOCUMENTVIEW_CN DROP COLUMN PARTITION#14, PARTITION#13, PARTITION#12, PARTITION#11, PARTITION#10, PARTITION#9, PARTITION#8, PARTITION#7, PARTITION#6, PARTITION#5, PARTITION#4, PARTITION#3, PARTITION#2, DATAAREAID#14, DATAAREAID#9, DATAAREAID#5, DATAAREAID#3

Man konnte den Fehler nicht aus dem AX heraus beheben, dafür musste man auf dem SQL Server die fehlerhafte View löschen selbst vom SQL-Server löschen.
 
DROP VIEW TAXINTGREXPORTDOCUMENTVIEW_CN
 
Danach konnte die Datenbank wieder normal Synchronisiert werden.
http://community.dynamics.com/ax/f/33/t/103490.aspx

Montag, 31. März 2014

Kompilierung im AX2012 mit AxBuild.exe


Ab dem  CU7 gibt es für AX2012 R2 ein neues Command Line Utility namens AxBuild.exe, mit dem das Kompilieren parallel über die Kommandozeile ohne den „Bottelneck“ des AX-Clients durchgeführt werden kann.

Mit Hilfe der AxBuild.exe konnten wir den gesamten X++ Source unserer Entwicklung in ca. 30 Min Kompilieren.

Dienstag, 18. März 2014

Fehler „Mixed mode assembly is built against version „v2.0.50727“ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information." für Visual Studio 2012 WCF Projekte gehosted von Visual Studio 2012 beheben.

Um eine Anbindung eines Archiv System an ein von Entwickeltes AX 2009 Modul zu ermöglich, ohne das eine Direkte Zugriff auf die eigentliche AX Datenbank zu gewähren. Wird von uns ein WCF Dienst eingesetzt der von einem externen Dienstleister konsumiert wird. Innerhalb des WCF Dienstes ist wurde die WCF Host Konfiguration. Um den Folgenden Eintrag erweitert:
 
<startup useLegacyV2RuntimeActivationPolicy="true">
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
Somit kann der Eigentliche Dienst ohne Probleme im Mixed assembly mode arbeiten.
Jedoch bin ich beim Testen des Dienstes immer wieder auf diesen Fehler gestoßen, wenn der WCF Dienst vom Visual Studio gehostet wurden.
Nach langen suchen bin ich auf folgende Lösung gestoßen:
 
Hier wurde die eigentliche Konfiguration angepasst, die vom Visual Studio verwendet wird. In der Standard Installation sollte die WcfScvHost.exe.config unter C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE zu finden sein. Hier wurde die WcfScvHost.exe.config um den entsprechenden Eintrag erweitert.
Meine WcfScvHost.exe.config sieht nun wie folgt aus:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
                <startup useLegacyV2RuntimeActivationPolicy="true">
                                <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
                </startup>
                <runtime>
                               <DisableMSIPeek enabled="true"/>
                </runtime>
</configuration>

Montag, 27. Januar 2014

Windows Phone 8 Gestengesteuerte Seitenwechsle

Im ersten Moment war es mir ein Rätzel wie ich einen simplen Seiten Aufruf, für Windows Phone 8 gestengesteuert implementieren sollte. Viel Beispiele und Implementieren Basieren auf dem Silverlight Toolkit für Windows Phone.
Leider ist diese Toolkit für Windows Phone 8 Obsolet, ich habe lange gesucht bis ich auf folgenden Link gestoßen bin.



Wie immer sind die einfachsten Lösungen meist die effektivste, hier wir entsprechend auf das ManipulationCompleted Event des jeweiligen Controls reagiert. Entsprechend der Bewegung Richtung kann man seinen eigenen Seiten Aufruf platzieren.

private void LayoutRoot_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
        {
            double dY = e.TotalManipulation.Translation.Y;
            double dX = e.TotalManipulation.Translation.X; 

            if (Math.Abs(dY) > Math.Abs(dX))
            {
                // Vertical
            }
            else
            {
                // Horizontal
                if (dX < 0)
                {
                    NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
                }
            }
        }

Freitag, 10. Januar 2014

AX2009 Methoden in einen Thread ausführen.

Die ganze Idee der Schaffung eines separaten Thread, um einen Prozess durchzuführen ist eine anerkannte Technik, um mit Multi-Prozesse zu einem bestimmten Zeitpunkt separate Anwendungs-Thread zu schaffen, auf die die Benutzeranwendung zugreift.

Bei Dynamics AX, ist es manchmal nicht so einfach, zu erkennen wo und warum Sie das Themen Multi-Threading verwenden sollten, um einen bestimmten Prozess oder Entwicklungsziel zu erreichen.
In meinem Fall war es, dass ein Prozess des Main Thread. Das weiterarbeitet der Nutzer verzögert, bis der Prozess beendet wurde. Es lag nun nahe diese länger in einen eigenen Thread laufen zu lassen.
Das folgende Beispiel soll zeigen wie man einen Dynamics AX Prozess in einen eigenen Thread ausführen kann. Hierbei war mir eine Rückmeldung der Prozesse nicht wichtig.
Für dieses Beispiel habe ich einen Job erstellt der einen entsprechenden Prozess einer Klasse Kapselt.

static void ThreadJob(Args _args)
{
    Thread              t;
    ExecutePermission   perm;
    container           con;
    ;
    perm = new ExecutePermission();
    perm.assert();
…   // create new thread
    t = new Thread();
    //set parameter values
    con = conins(con,1,’param1’);
    con = conins(con,2,’param2’);
    t.setInputParm(con);
    // run thread
    t.run(classnum(LongProcess), staticMethodstr(LongProcess, ThreadExecute));
}
 

Die Methode “ThreadExecute” der Klasse “LongProcess” beinhält den eigentlichen Source des Prozess.
server static void ThreadExecute(Thread T)
{
    container                 ThParams = T.getInputParm();
    Set                       permissionSet;
    str                       param1;
    int                       param2;
    ;
    permissionSet =  new Set(Types::Class);
    permissionSet.add(new InteropPermission(InteropKind::ClrInterop));
    CodeAccessPermission::assertMultiple(permissionSet);

   //get parameter values
   param1= conpeek(ThParams, 1);
   param2= conpeek(ThParams, 2);
   // run long term process  
   // ………
   

   CodeAccessPermission::revertAssert();

}
  
 
 

 

Mittwoch, 18. Dezember 2013

Drucken eines externen PDF aus AX2009 mit Hilfe des Adobe Readers.

static void printPDF(str _filePath, PrintJobSettings  _printJobSettings = new PrintJobSettings() )
{
    PrintJobSettings    printJobSettings;
    str                          adobeExe;
    str                          adobeParm;
    Set                         permissionSet;
    ;

    permissionSet = new Set(Types::Class);
    permissionSet.add( new InteropPermission(InteropKind::ClrInterop) );
    CodeAccessPermission::assertMultiple( permissionSet );

    if (System.IO.File::Exists(_filePath))
    {
        //get Adobe Reader executable
        adobeExe = WinAPI::findExecutable(_filePath);
      
        adobeParm = strFmt('/n /t "%1" "%2" "%3" "%4"',
                           _filePath,
                           printJobSettings.printerPrinterName(),
                           printJobSettings.printerDriverName(),
                           printJobSettings.printerPortName());

        winAPI::shellExecute(adobeExe,  adobeParm);
    }
    CodeAccessPermission::revertAssert();
}

Adobe Commandline Arguments:
http://www.robvanderwoude.com/commandlineswitches.php#Acrobat

Donnerstag, 7. November 2013

WinApi::CreateDirectoryPath verursacht Fehler bei Verwendung von UNC Pfaden

Bei der Umstellung der Version Kontrolle von relativen Pfaden hin zu UNC Pfaden musste ich feststellen das die Methode WINAPI::CreateDirectoryPath nicht mit UNC Pfaden arbeiten kann. Es wird  folgender Fehlermeldung ausgegeben:

"ClrObject static method invocation error"

Es hat eine Weile gedauert aber dann bin ich auf eine funktionierende Lösung gestoßen.

// Verifyes or creates Path
static client public boolean createDirectoryPath(FilePath _path)
{
         int ptr;
         ;

         _path = strLRTrim(_path);

         if (substr(_path,strlen(_path),1) != '\\') // Adding backslash gives a more simple while-loop!
         {
                 _path += '\\';
         }

         //enables creation of UNC paths, by detecting which folder already exists (backwards).
         ptr = strLen(_path);
         ptr = strfind(_path, '\\', ptr, -ptr);
         while(!WinAPI::folderExists(substr(_path,1,ptr)))
         {
                  ptr = strfind(_path, '\\', ptr -1 , -ptr);
         }

         while (ptr)
         {
                 WinAPI::createDirectory(substr(_path, 1, ptr));

                 if (!WinAPI::folderExists(substr(_path, 1, ptr)))
                {
                        break;
                }

                ptr = strfind(_path, '\\', ptr + 1, strlen(_path));
         }

         return WinAPI::folderExists(_path);
}

Verwendung von Team Foundation Server 2012 als Versionskontrolle für AX 2009

Grundsätzlich kann man für die Installation und Integration die Step by Step Anleitung aus folgenden Blog verwenden http://blog.enhancealm.com.au/2011/03/08/dynamics-ax-development-using-tfs-2010/. Das Vorgehen für TFS2010 ist auf TFS2012 übertragbar.

Problematischer stellte sich die Integration in unserer Multi Developer Umgebung da. Wir verwenden für die Entwicklung von AX2009, Citrix Clients. Über die der jeweilige Entwickler auf den AOS zugreift. AX2009 kennt standardmäßig nur einen Speicherort für das lokale Repository. Um für jeden Entwickler ein lokales Repository zu verwenden musste die AX Klasse SysVersionControlParameters angepasst werden, um eine eigenes Repository mit der Benutzerkennung zu erstellen.

    #SysVersionControl
    SysVersionControlParameters parameter;
    ;
    parameter.selectForUpdate(_forupdate);
    select firstonly parameter
        index Key
        where parameter.Key == 0;

    if(parameter)
    {
        if(parameter.VCSType == SysVersionControlType::SysVersionControlTfs)
        {
            parameter.RepositoryFolder = strFmt("%1_%2",parameter.RepositoryFolder,curUserId());
            new InteropPermission( InteropKind::ClrInterop ).assert();
            if(!WinApi::pathExists(parameter.RepositoryFolder))
            {
               WinApi::createDirectoryPath(parameter.RepositoryFolder);
                info('Nur für Entwickler:\r\nBitte Repository manuell synchronisieren');
            }
        }
    }
.
.
.

Bei der Angabe des Repository für die AX Versions Kontrolle Parameters wird nun nur der Pfad zum Basisordner für alle Entwickler Repository angegeben werden.

Samstag, 10. August 2013

Beheben von Timeout Problemen bei Skriptausführung

Bei der Verarbeitung von Querys oder Aufruf von Methoden im AX, die ein längere Laufzeit haben. kann es vorkommen das der Timeout des WebParts überschritten wird. Um dies zu verhindern kann man den Timeout beim betreffenden WebControls erhöht werden.

using System.Web.UI;

protected void Page_Load(object sender, EventArgs e) 
{
  
 ScriptManager scripts = ScriptManager.GetCurrent(this.Page);
        if (scripts != null)
 {
   scripts.AsyncPostBackTimeout = 600; 
 } 
}
 
In diesem Source Beispiel wird der Postback Timeout vom 600 Sekunden erhöht, der Standardwert ist 90 Sekunden.

Verwendung von AX Labels im Enterprise Portal

Neben der durch Feldbezeichnungen und Feldgruppen automatisch durchgeführte Label Nutzung, können im Enterprise Portal einzelne Labes aus den Label Dateien genutzt werden. Hierfür muss die jeweilige LabelId bekannt sein und die jeweiligen Label Dateien auf dem AOS-Server ausgeliefert sein.

Grundsätzlich gibt es zwei Möglichkeiten auf die Labels innerhalb des Enterprise Portals zuzugreifen. Zum einen über das ASP .NET-Markup oder aus dem Source des jeweiligen Web oder auch User Controls.

ASP .NET-Markup

Sie können Labels von Microsoft Dynamics AX in der Markup für eines Web oder User Controls verwenden.

<%$label:@SYS1234%>

Der um für das Label nun das jeweiligen Lokalisierten Label aus AX zu verwenden. Kann das folgt  ASP.NET-Markup verwendet werden.

<asp:Label ID="Label1" runat="server" Text="<%$axlabel:@SYS1234%>"></asp:Label>

Source Code

Microsoft Dynamics AX Label können auch in Source des Web oder des User Controls verwendet werden. Hier für wird die Labels Klasse das dem Namespace Microsoft.Dynamics.Framework.Portal.UI benötigt. Diese stellt die Methode GetLabel zum auslesen des AX Labels zur Verfügung.

this.PageDefinition.pageTitle = Labels.GetLabel("@SYS131104");

siehe auch AX 2009 EP Development CookBook