Quantcast
Channel: AXForum
Viewing all 14626 articles
Browse latest View live

sertandev: AX7 Extensibility Overview – Part 2 : Code extensions

$
0
0
Источник: https://sertandev.wordpress.com/2017...de-extensions/
==============

We have seen an overview of what we can do with application object extensions in the first part of this blog. Now what if we want to modify the program code or add new methods and variables to the program code of an existing object in AX7? It is possible to do it in various ways in AX7 (or D365O).

First method is of course the legacy method of creating a derived class which we want to extend, adding or overriding base methods in it and use this class in our new model instead of the base class. This solves many of the customization work we need but there might be cases this method is not desirable or we cannot modify the code of existing tables and forms like that.

Second option is to create something new called an ‘extension class’ to extend the program code of an existing object. This is simply done by creating an extension class with the template shown below using the ‘ExtensionOf’ attribute:

[ExtensionOf(classStr(MyClass))]final class MyClass_Extension{private int myParm;private void new(){}public int parmMyParm(int _myParm = myParm){myparm = _myParm;return myParm;}public static MyClass constructFromMyParm(int _myParm){MyClass myClass;myClass = new MyClass();myClass.parmMyParm(_myParm);return myClass;}}This way you can add new methods, variables, constructors and static methods directly added to the base class instead of using a derived class. After this, you can call the new methods and constructors you have added in your extension class directly from the base class itself, such as:

MyClass::constructFromMyParm(24).

The suffix of the extension class you have created must be ‘_Extension’ and you can name the MyClass part with anything you want, it does not have to be the base class name. Same way you can create code extensions for tables and forms (as of version update2) as well, later we will try an example with each.

Although this looks like a derived class construction, the extension class is not a derived class from the base and you cannot access private and protected methods and variables, nor override existing methods of the base class here. But it is possible to access public methods and variables of the base class as well as using ‘this’ keyword in your method declarations to access those. It is also possible to access the methods of other extensions on the same base object if you have added the model that includes the other extension class in your model definition’s referenced packages.

I also want to mention the extension class template below. Before the “Update1” version of AX7, the template for creating the extension class for tables and classes was like below :

public static class MyClass_Extension{public static int parmMyParm(MyClass _this, int _myParm = myParm){myparm = _myParm;return myParm;}}Here you declare your class and all the class methods as static (class with _Extension suffix) and add the object you want to extend as the first parameter of your method. I do not recommend using this template in your new program code because the new one is more readable and useful, but be aware: On runtime your new notation extension class works exactly the same way using static method calls, just like the old notation did. This is why you cannot access class private and protected variables nor override existing methods in it. Also for the same reason you should not create a direct instance of the extension class in your program code, nor create another class derived from your extension class (it also receives a “sealed” attribute when built into CIL, like other static classes in .net). You can confirm it for yourself using visual studio debugger:



Creating table methods is pretty the same, you can even create new display and edit methods as shown below, to be used in a form (or form extension) in the same model :

[ExtensionOf(tableStr(InventTable))]final class ExtensionDemo_Extension{private void new(){}[SysClientCacheDataMethodAttribute(true)]public display Description dispExtendedDesc(){return this.Description5+this.Description6;}}To be able to use this display method in your form, you need to define the “Data method” property of your data field like this, using static method operator and name of your extension class (“ExtensionDemo_Extension::dispExtendedDesc”). Directly writing the method name will not work :



Form extensions are created pretty much the same way. The newly added methods are accessible from the form and its extensions. The ‘this’ object in your extension contains the element object (FormRun) of the extended form, so you can query for elements and data sources easily from here. Here is an example how to use element variables in a form extension class in various different ways :

[ExtensionOf( formstr( ExtensionDemoForm ))]final class ExtensionDemoForm_Extension{ private boolean hasArgs; private void new() {} public boolean parmHasArgs(boolean _hasArgs = hasArgs) { hasArgs = _hasArgs; return hasArgs; } public boolean hasArgsRecord() { return (this.args().record()!=null); } [FormEventHandler(formStr(ExtensionDemoForm), FormEventType::Initialized)] public void ExtensionDemoForm_OnInitialized(xFormRun sender, FormEventArgs e) { this.parmHasArgs((this.args()!=null)); }}Note that the event handler here does not have the ‘static’ keyword, but instead declared as a class instance method intentionally removing the static keyword from the definition. It is possible to declare some of the event handlers like that then you can use ‘this’ keyword to access methods and variables defined in the same class from a eventhandler (more on eventhandlers on Part3).

You can add a simple click method and test our extension method inside the form :

public void clicked(){super();info(strFmt("Has args?: %1", element.parmHasArgs()));info(strFmt("Has args record?: %1", element.hasArgsRecord()));}

Eventually it is also possible to override form control and data field methods from the form extension class, which gives you much more flexibility in creating extensions for forms:

[ExtensionOf( formstr( ExtensionDemoForm ))]public final class ExtensionDemoForm_Extension{public void clickedOverride(){info(strFmt("Name : %1", this.name()));}[FormEventHandler(formStr(ExtensionDemoForm), FormEventType::Initialized)]public void ExtensionDemoForm_OnInitialized(xFormRun sender, FormEventArgs e){FormButtonControl button = this.design().controlName(formControlStr(ExtensionDemoForm,FormButtonControl1));button.registerOverrideMethod(methodStr(FormButtonControl,clicked),'clickedOverride', this);}}A note on form class extensions: In this time of writing (Update 3 version), not everything with form class extensions work all right, it has some bugs which are already reported to Microsoft. For example the code above compiles ok but on runtime the method above is not accesible from the Formrun class, although the previous example compiles and runs just fine (just using ‘this’ keyword in the same class). I will post an update if things change in the future on that part.

Plugins

Plugins are yet another way to extend code in new AX7 besides the extension methods we mentioned above. Plugins use attributes to create new subclasses and subclass methods which can be used as alternatives to existing classes and methods belonging to same plugin base and can be initialized using a string type of key from the SysPluginFactory class. This way you can also choose which plugin to use by selecting it with a string parameter. I will not get into the details of using plugins and the attributes used in plugin framework but perhaps I might write another blog about them in the future.

For more information on code extensions you can check the wiki article at : https://ax.help.dynamics.com/en/wiki/class-extensions/




Источник: https://sertandev.wordpress.com/2017...de-extensions/

sertandev: AX7 Extensibility – Part 3 : Event handlers and delegates (hooks)

$
0
0
Источник: https://sertandev.wordpress.com/2017...legates-hooks/
==============

In the previous blog post we had a look at the possibilities of adding new methods and variables to existing AX7 program code using extensions. What if we need to modify, or add extra functionality to existing methods or events on existing classes, tables and forms? In that case we use AX7 events and delegates (also called ‘hooks’).

There are already plenty of events (hooks) we can subscribe in AX and extend the existing functionality without overlayering or overriding the function we need to extend. You can find those under the “Events” node of the application objects. Subscription is as easy as right clicking and selecting “Copy event handler method”, then you need to paste it into an eventhandler class and write your own logic inside:

public static class ExtensionDemoInventTableEventHandlers{[DataEventHandler(tableStr(InventTable), DataEventType::Deleted)]public static void InventTable_onDeleted(Common sender, DataEventArgs e){ InventTable inventTable = sender as InventTable;//Your logic}}Here I have subscribed to the ‘Deleted’ event of the table. Note that the object methods (like insert, update, init, write..) we used to override in the AX 2012 now corresponds to two different events, as ‘Deleting’ and ‘Deleted’, and we no more call super() in our event handler methods. The execution of those compared to AX2012 works like below:

public void delete(){.... //Existing code before superEvent_onDeleting();super();Event_onDeleted();.... //Existing code after super}As a good practice you can place those event handlers in a static class which you suffix with ‘EventHandlers’ (which is not mandatory), or inside the extension class you have created for that object. On all events you subscribe you also have a parameter that contains an “event args” object for the corresponding event. However this parameter is not always the event args class you exactly need.. They are generally downcasted to their most common base class (DataEventArgs for data related events or FormEventArgs for events on the form root) and you need to cast it back to the args class you need. See the validatedFieldValue eventhandler below as an example :

[DataEventHandler(tableStr(InventTable), DataEventType::ValidatedFieldValue)]public static void InventTable_onValidatedFieldValue(Common sender, DataEventArgs e){ InventTable inventTable = sender as InventTable; ValidateFieldValueEventArgs ve = e as ValidateFieldValueEventArgs; boolean ret = ve.parmValidateResult(); if(ret) { switch(ve.parmFieldName()) { case fieldStr(InventTable,Description5): if(InventTable.Description5=="") { ret = false; } break; } }ve.parmValidateResult(ret);}

There are a lot of event handlers with downcasted parameters like this one and it is impossible to list all of them here. You can investigate existing code for that and I recommend you to create yourself a template document with templates to cast the Args parameters or reach other objects using the args or “sender” parameters within the eventhandler (if I grow one, i will share it here).

Beyond these events listed inside the Events node, there are Pre and Post event handlers which you can subscribe to existing public methods, and run your own logic before or after the original method is executed. And it is possible to change the return type and access the method parameters using the XppPrePostEventArgs parameter like the example below:

[PreHandlerFor(tableStr(InventTable), tableMethodStr(InventTable, defaultField))]public static void InventTable_Pre_defaultField(XppPrePostArgs args){ InventTable inventTable = Args.getThis() as InventTable; FieldId parmFieldId = Args.getArg('_fieldId'); switch(parmFieldId) { case fieldNum(InventTable, Description5) : InventTable.Description5 = ''; break; }}[PostHandlerFor(tableStr(InventTable), tableMethodStr(InventTable, isBOMAllowed))]public static void InventTable_Post_isBOMAllowed(XppPrePostArgs args){ InventTable inventTable = Args.getThis() as InventTable; boolean ret = Args.getReturnValue(); if(ret) { ret = (inventtable.Description5 != ""); }Args.setReturnValue(ret);}By default, you cannot subscribe to protected or private methods, but there is a workaround to be able to subscribe those. You can customize the object that holds the method by overlayering and add the following attribute on top of the method. Then you will be able to add pre and post handlers to that method regardless of protected or private modifier :

[HookableAttribute(true)]protected boolean parmHasArgs(boolean _hasArgs = hasArgs){ hasArgs = _hasArgs; return hasArgs;}To be able to query existing eventhandlers one event has, simply right click and select “Find event handlers” :



We have seen how to use existing events and how to add extended code before or after a method call. What if we need to modify a method by inserting program code in the middle of its program code? In that case we use delegate methods just as in AX2012. Subscribing to a delegate function is as shown below:



Then paste it into your extension, or event handler class:

[SubscribesTo(classStr(LedgerJournalCheckPost), delegateStr(LedgerJournalCheckPost, runInternalPostPostJournalDelegate))] public static void LedgerJournalCheckPost_runInternalPostPostJournalDelegate(LedgerJournalCheckPost _ledgerJournalCheckPost, boolean _postingSuccess, boolean _intercompanyPostingSuccess) { //Your own logic }There are already many delegate functions in key classes published by Microsoft and we can add new ones by overlayering these classes ourselves. If you do not want to use overlayering, in the time of writing, there is an option to book a request in Microsoft in Visual Studio Online and ask them to add a delegate to a system method for you, which is not accessible for everyone (I think only for the companies in the development program). You can ask your administration if this is available for your company. If you would like to create a delegate in your own code to allow subscription, you declare it like below. Then from the designer window of your class you can subscribe to your own delegate:

class ExtensionDemoDelegateTest{void new(){}public void showMessages(){Description message='Internal message text';info('Before..');this.showMessageText(Message);info('After...');}delegate void showMessageText(Description _msg) {}public static void main(Args _args){ExtensionDemoDelegateTest test;test = new ExtensionDemoDelegateTest();test.showMessages();}}

static class ExtensionDemoDelegateTestEventHandlers{//Handler 1[SubscribesTo(classStr(ExtensionDemoDelegateTest), delegateStr(ExtensionDemoDelegateTest, showMessageText))]public static void ExtensionDemoDelegateTest_showMessageText(Description _msg){info('Message echo from the event handler: '+_msg);}//Handler2[SubscribesTo(classStr(ExtensionDemoDelegateTest), delegateStr(ExtensionDemoDelegateTest, showMessageText))]public static void ExtensionDemoDelegateTest_showMessageText2(Description _msg){info('Message echo from the event handler 2: '+_msg);}}When we run the class :



As you see we can add as much hooks (or eventhandlers) as we want and they will run when the delegate is called inside the class method. Remember in AX, just like .NET, there is no guarantee on execution order of the eventhandlers subscribed to a delegate method. So never assume in your code that the first eventhandler you write will execute before the second or so, that is not guaranteed.

That is all about the event handlers in this blog. For more information on event handlers and delegates, you can check the wiki articles at :

https://ax.help.dynamics.com/en/wiki...y-and-keywords

https://ax.help.dynamics.com/en/wiki...and-extensions




Источник: https://sertandev.wordpress.com/2017...legates-hooks/

sertandev: Using base64 encoding and decoding for file transfer in AX 2012

$
0
0
Источник: https://sertandev.wordpress.com/2017...er-in-ax-2012/
==============

If you want to transfer small file data using AX and do not want to make use of shared folders or file uploading, sending your file directly inside your XML message as base64 encoded string is a good option. Base64 gives you the possibility to encode your binary data as text and transfer it inside text based message types like XML and JSON and decode it back as a file on the receipt.

For big files though, like 10MB and bigger, I recommend using binary file transfer instead of base64.

Ax 2012 has built in support for decoding and encoding base64 data type with some missing things and drawback we will mention in this article. I do recommend using AX standard methods to do it and not .NET equivalents in AX 2012, because I doubt marshalling such huge amount of data between CLR Interop and AX performs good enough.

Encoding base64 from AX data

For decoding from AX table stored, container based data, simply use the following function:

public str base64FromData(container _data){str base64;Bindata bindata;if(_data!=conNull()){bindata = new bindata();bindata.setData(_data);base64 = bindata.base64Encode();}return base64;}You can use the same bindata class to load a file from disk instead of loading a container based binary data from database. Do not forget to add a CLR interop permission for this to avoid the error :

///.....................path = docuRef.completeFilename();fileIOPerm = new FileIOPermission(path,'r');permissionSet.add(fileIOPerm);interopPerm = new InteropPermission(InteropKind::ClrInterop);permissionSet.add(interopPerm);CodeAccessPermission::assertMultiple(permissionSet);fileExists = System.IO.File::Exists(path);if(fileExists){bindata.loadFile(path);base64 = bindata.base64Encode();}//////////////.....................If you want to encode simple text (or memo, string) using base64 and send it as base64, you need to load the string to bindata class using setAsciiData() method. Note that bindata class also has a setText() method, we are NOT using that one, it will encode it wrong if you do so:

str Memo = "a string";bindata.setAsciiData(Memo);After your file is decoded you can add it directly as a node value in your XML document.

Decoding base64 file from a document

Here is the tricky part, AX decodes base64 fine but causing some problems on base64 prefixes. It does not recognize them. To be able to decode it, you manually need to remove the headers, like the example below, and decode it :

public container dataFromBase64(str _base64){int pos;BinData    bindata;str base64, base64ext;container   data;base64 = _base64;base64ext = '';if(base64!=''){pos = strFind(base64, ';', 1, 60);if(pos){base64ext = subStr(base64, 1, pos-1);}pos = strFind(base64, ',', 1, 60);base64 = strDel(base64, 1, pos);bindata = new bindata();data = BinData::loadFromBase64(base64);bindata.setData(data);}return data;}What are those headers and when they come. Some types of base64 data, for example photos taken from a cellphone camera in base64 encoding or images used in web, has descriptor prefix before the data starts. Such as the data below. You can erase them to be able to encode, or store them in a variable, like the code above to determine the file extension of the data later.



After you decode your data into container, you can load it into bindata class (like example above) and save it as file or another form of data using bindata class.

Here are some more tips for you if you want to decode base64 and store it inside AX:
  • Do not store big file data in a container or string memo blob field in an AX table if you plan to use that table in AX user interface, like inside a form. Create a separate table to store the data and reference other tables to that one if they want to use the file data. It gives all sorts of problems if you store your data in a table used in a form or other UI object, for example if you want to delete the data from the form, it crashes the client (whereas deleting from the code works fine from the same table).
  • If you like to store the XML message you have received with file data, for logging or archive purposes, first strip all the file data out of it and do not store the XML text including base64 data inside. You will again have similar problems like above and if you use AIF XML viewer, it will take ages to load that XML into the viewer. You can replace base64 text with the recid of the data you have stored in your data storage table.




Источник: https://sertandev.wordpress.com/2017...er-in-ax-2012/

sertandev: Using 3rd party Web components in AX7; an introduction to extensible controls

$
0
0
Источник: https://sertandev.wordpress.com/2017...ible-controls/
==============

AX7 allows you to develop new user interface components called ‘extensible controls’ using HTML, Javascript and other web programming technologies. You can also integrate any of the thousands of existing web based plugins and code libraries inside AX user interface and use them directly with AX data. Building ‘extensible controls’ in AX offers endless possibilities to enrich standard AX7 user interface and forms.

However, learning how to write an extensible control is a subject of its own. It is not straightforward and simple as programming other parts of AX and I think having a good knowledge in HTML and web programming is a must to be able to understand it. The documentation and github examples provided by Microsoft is limited, but by studying the functionality yourself, doing examples and examining existing controls in AX7 webroot folder, pieces of the puzzle start to fit together.

Here in this article I will show the basics of how to integrate a third party web plugin and use it in an AX7 form. I have chosen weareoutman’s ClockPicker as an example and will show how to create an alternative, better looking AX time edit control with this plugin and add it to AX forms:



Please download the latest SDK for the plugin from the link below, and study the readme file before you start using the SDK (MIT license) :

https://weareoutman.github.io/clockpicker/

Control’s HTML document

First we need to create a simple HTML document which contains our control and links to it’s script libraries like below. AX7 web application already uses JQuery, so you do not need to link it in your web page, but it does not use ‘bootstrap’, and I do not recommend adding bootstrap to AX7 web pages. In fact, be really careful that the libraries or style sheets you add here in your control document dont conflict with AX7 standard code and styles. AX7 uses its own UI library, so we skip the bootstrap option for the plugin and use it without. Our basic HTML document looks like this :


The $data variable holds the properties of our control’s current data instance (we will come to that later) and we can dynamically bind the control properties of AX7 to various properties of the HTML element using “data-dyn-bind” property AX7 provides for us. After it is bound dynamically, anytime you change the value in AX7 code, it is reflected to the HTML control, so AX code and HTML side is linked. There are so many useful other “data-dyn-bind” functions that you can create server side (ASP) programming like functionalities, such as conditional if blocks and foreach loops. Please check “Extensible control programming reference” from the links below for a list of those interesting functions.
We could have used “data-dyn-bind=”attr: {value: $data.DefaultTime}”” on our input element to dynamically bind our control’s value to the HTML input element’s value attribute; but in our example, that does not work. The initialization of the clockpicker plugin destroys the binding done on the input element by the data-dyn-bind attribute.

The css classes I assigned are just copied from standard AX7 input boxes, by default AX does not have borders for input boxes and you need to set your classes correctly to be able to see your input control.

The scripts and style sheet links we add into our HTML are later parsed by AX7 application and inserted into the webpage header automatically if we use the control in our form. So we can add as much links here as we want.

The ClockPickerControl.js is our control’s javascript code; for now just create an empty Javascript for that and save it to your desktop.

Save your HTML file to your desktop, with extension “htm” instead of “html” and forward to next step of adding the resources.

Control’s Resources

In AX7, added resources consists of various web elements, like html pages, css sheets, images, javascript files which will be copied into the related directories of AX7 web application under “Resources” main folder:



Like we did in our HTML file above, we can then link to those resources using \Resource\ path. For our extensible control we need to insert the following resources which are being used by our HTML page above:



Control’s build class

On AX side, we need to create two classes for AX to recognize our control and add our control to AX control library: build class and runtime class. Our build class is the one which is used by the VS AX form designer, containing properties of our control. We add following properties, which “DefaultTime” being the value of our edit box :

[FormDesignControlAttribute("ClockPickerControl")]class ClockPickerControlBuild extends FormBuildControl{str defaultTime,doneText,label;[FormDesignPropertyAttribute("DefaultTime", "Data")]public str parmDefaultTime(str _defaultTime = defaultTime){if (!prmIsDefault(_defaultTime)){defaultTime = _defaultTime;}return defaultTime;}[FormDesignPropertyAttribute("DoneText", "Data")]public str parmDoneText(str _doneText = doneText){if (!prmIsDefault(_doneText)){doneText = _doneText;}return doneText;}[FormDesignPropertyAttribute("Label", "Appearance")]public str parmLabel(str _label = label){if (!prmIsDefault(_label)){label = _label;}return label;}}The second parameter in our method’s FormDesignPropertyAttribute() is the name of the tab page in properties window, which our property is displayed under; but at the time of writing that does not work, all added attributes appear in “Misc” tab in properties.

Control’s runtime class

This is the main class of our control which gets the design time properties from build class and sends them to HTML side for processing, also handles the runtime bindings on HTML side. Methods and variables with FormCommandAttribute or FormPropertyAttribute on this class can be accessed directly from the Javascript code of your control by using the ‘$control’ and ‘$data’ objects. For example, to be able to call a method in this class, you use ‘$dyn.callFunction()’ in JS. I will not cover all of it in this tutorial.

The HTML file for your control is linked in the header of this class in FormControlAttribute, or using this.setResourceBundleName method. The “template id” you set here for your control is important, this will be the unique name of your control which is used in AX, HTML and Javascript code of your control:

[FormControlAttribute('ClockPickerControl', '/Resources/html/ClockPickerControl', classstr(ClockPickerControlBuild))]class ClockPickerControl extends FormTemplateControl{FormProperty defaultTime;FormProperty doneText;FormProperty label;[FormPropertyAttribute(FormPropertyKind::Value, "DefaultTime")]public str parmDefaultTime(str _value = defaultTime.parmValue()){if (!prmIsDefault(_value)){defaultTime.setValueOrBinding(_value);}return defaultTime.parmValue();}[FormPropertyAttribute(FormPropertyKind::Value, "DoneText")]public str parmDonetext(str _value = doneText.parmValue()){if (!prmIsDefault(_value)){doneText.setValueOrBinding(_value);}return doneText.parmValue();}[FormPropertyAttribute(FormPropertyKind::Value, "Label")]public str parmLabel(str _value = label.parmValue()){if (!prmIsDefault(_value)){label.setValueOrBinding(_value);}return label.parmValue();}public void new(FormBuildControl _build, FormRun _formRun){super(_build, _formRun);this.setTemplateId('ClockPickerControl');this.setResourceBundleName('/Resources/html/ClockPickerControl');defaultTime = properties.addProperty(methodStr(ClockPickerControl, parmDefaultTime), Types::String);donetext = properties.addProperty(methodStr(ClockPickerControl, parmDoneText), Types::String);label = properties.addProperty(methodStr(ClockPickerControl, parmLabel), Types::String);}public void applyBuild(){super();ClockPickerControlBuild build = this.build();if (build){this.parmDefaultTime(build.parmDefaultTime());this.parmDoneText(build.parmDoneText());this.parmLabel(build.parmLabel());}}}Control’s Javascript code

To be able to initialize our control on JS side, we need to declare our control’s javascript object in a separate javascript file which we have linked in our HTML page before as “ClockPickerControl.js”. Object constructor definition for our control is assigned to $dyn.controls.ClockPickerControl variable with the same template id as the one we used in our runtime AX class (be careful to use same template id for your control in all those definitions, or your control will not work ok). And Javascript object prototype for our control is declared as inheriting from “$dyn.ui.Control” object. Here in the prototype declaration, you can add new properties and functions for your control which will be shared by all instances of your control (check “Javascript objects” for more information on object and prototype declarations)

The code below is mostly the basic template for all extensible control javascript files, except we need to call the plugin initialization for our clockpicker inpit element. Also because I could not dynamically bind the ”DefaultTime” value of my control to the HTML input element, I bind it manually using $dyn.observe method for my property and ‘change’ event of the input element:

(function () {'use strict';$dyn.controls.ClockPickerControl = function (data, element) {$dyn.ui.Control.apply(this, arguments);var self = this;self.$clockPickerElement = $(element).find("input");self.$clockPickerElement.clockpicker({donetext: data.DoneText,twelvehour: true,autoclose:true});self.$clockPickerElement.change(function () {data.DefaultTime(self.$clockPickerElement.val());});$dyn.observe(data.DefaultTime, function (defaultTime) { self.$clockPickerElement.val(defaultTime) })};$dyn.controls.ClockPickerControl.prototype = $dyn.ui.extendPrototype($dyn.ui.Control.prototype, {init: function (data, element) {$dyn.ui.Control.prototype.init.apply(this, arguments);}});})();Using the $dyn.observe() method, you can add event handlers to changes in AX7 Web API ‘observable’ variables. By default all control properties are observable variables and you can create more observable variables in AX7 JS API if you need. You can then attach event handlers to track changes to those variables. Please check the reference document for examples and more information on that.

Putting it together

After you build your solution, you can see your new control on the ax controls list and add it to your form :



And you can set the properties of the control from the standard ax properties window and run your form.

Also the properties you have added are acessible from the program code, just like other form controls in AX :

[Control("Button")] class DisplayTime { /// <summary> /// /// </summary> public void clicked() { super();info(ClockPickerControl1.parmDefaultTime()); }}[Control("Button")] class SetTime { /// <summary> /// /// </summary> public void clicked() { super();ClockPickerControl1.parmDefaultTime("5:30AM"); }}

That’s all the basics for now, if you want to extend the control further, you can make the time property as a time datatype, add view/edit mode support, new control properties for 12 hour mode and others, bind it to a data source and make it multi language, just there are so many possibilities..

You can download the source code of this blog post from the following link :

https://github.com/sertanyaman/Serta...ontrolDemo.zip

Other useful links to study on AX7 extensible controls :

extensible-control-programming-reference

Dynamics-AX-Extensible-Control-Samples Github

build-extensible-control

extensible-controls-layout










Источник: https://sertandev.wordpress.com/2017...ible-controls/

Вакансия разработчик C# / .net удаленная работа, РФ

$
0
0
Ищем разработчика C#/.NET

работодатель - крупная страховая компания, TOP 10
характер работы - УДАЛЕНКА, МСК 9-18 (+/-)
наличие стабильного канала Интернет обязательно.

Ждем ваше резюме - на resharper20@yandex.ru

ФОТ - достойный.

готов ответить на вопросы
=======================
ОБЯЗАННОСТИ
• Модификация корпоративной информационной системы, написанной на языке программирования C#
• Автоматизация процессов внутри ИТ подразделений (системы управления проектами, системы баг трекинга (Jira, TFS и т.д.) и прочее)
• Разработка Web-приложений, Desktop-приложений
• Разработка клиентской части на (MVC, WPF)
• Разработка WCF-сервисов;
• Работа с транспортными форматами XML, JSON
• Работа с БД MS SQLServer, Oracle
• Создание многопоточных приложений
• Разработка отчетов на основе данных, извлекаемых из разных источников (сервисы, БД, файлы и пр.);
• Проведение анализа и формирование требований на выполнение доработок;
• Интервьюирование бизнес-пользователей
• Взаимодействие в команде разработчиков

ТРЕБОВАНИЯ
Оконченное высшее образование, желательно – в области кибернетики, информационных технологий, автоматизированных систем управления

Опыт работы в ИТ компаниях или ИТ подразделениях крупных компаний на должностях связанных с разработкой программного обеспечения

Продвинутый пользователь ПК, знание MS SQL Server (на уровне написания сложных запросов, хранимых функций и процедур); Хорошее знание:
MS SQL Server (T-SQL), Oracle (PL/SQL),
C#, .NET, ADO.Net, WPF, WCF, MVC
XML (XSD, XSLT)
HTML, CSS, JS, AJAX, JQuery
Желательно знание продуктов JetBrains IntelliJ IDEA или Eclipse

Хорошее знание основных принципов ООП и их использование на практике.
Знание основных шаблонов проектирования информационных систем и умение применять их на практике
Понимание принципов построения реляционных БД;
Опыт разработки распределенных приложений
Навыки построения потокобезопасных приложений
Хорошие знания: Веб-сервисы SOAP, RESTful; XML(XSD, XPath, XSLT);
Умение хорошо разбираться в коде других разработчиков
Умение вести проектную документацию
Желательно: знание и опыт работы со средствами командной разработки (TFS, Git);

Усидчивость, ответственность, коммуникабельность, умение работать в команде

Разработчик Axapta, Москва

$
0
0
Ищем в команду разработчика AX, на полную занятость.
Компания занимается дистрибуцией компьютерного оборудования и программного обеспечения

Контакты:
axapta17@gmail.com или пишите в личку

Требования:
•Опыт разработки в DAX от 3 лет;
•Знание X++, SQL;
•Опыт интеграции Axapta с внешними системами (веб-сервисы, хранимые процедуры);
•Умение выявлять и устранять причины проблем производительности (использование DynamicsPerf или других инструментов);
•Умение администрировать БД DAX (Microsoft SQL Server);

Обязанности:
•Реализация доработок в DAX2012 по заданию аналитика;
•Обеспечение бесперебойного функционирования DAX2012 и интеграционных механизмов;
•Помощь аналитикам в поиске и исправлении системных ошибок;
•Подготовка и выпуск релизов;
•Перенос изменений между платформами (DEV,TEST, PROD);
•Участие в проектах внедрения новых функциональных модулей.

Условия:
•Стабильная заработная плата;
•Социальный пакет;
•Возможность профессионального и карьерного роста;

emeadaxsupport: Dynamics 365 for Finance and Operations – Requesting a ‘Database refresh’ – Enable user access

$
0
0
Источник: https://blogs.msdn.microsoft.com/axs...e-user-access/
==============

As I am sure you are already aware, you can now submit requests directly to the Dynamics Service Engineering (DSE) team by using Lifecycle Services (LCS). Submit a request to the Dynamics Service Engineering team https://docs.microsoft.com/en-us/dyn...gineering-team One of the request types that you can select is the Database refresh, which includes the ability to refresh... Read more

Источник: https://blogs.msdn.microsoft.com/axs...e-user-access/

emeadaxsupport: Production order end process results in variances due to differences in estimated and realized subassembly setup labor costs.

$
0
0
Источник: https://blogs.msdn.microsoft.com/axs...p-labor-costs/
==============

The issue that we were initially encountering was that we were experiencing large variances in our production costing.  Upon further investigation, what we found was that the variances were coming from a subassembly that had been created and was being utilized in the finished good.  Reviewing the details on that subassembly and comparing to our... Read more

Источник: https://blogs.msdn.microsoft.com/axs...p-labor-costs/

D365FO - Как вывести на печать нижний колонтитул в отчёте по клиенту

$
0
0
Всем привет!

Подскажите, пожалуйста, как можно вывести на печать нижний колонтитул в отчёте о клиенте? Вроде всё настройки есть, а на печати ничего нет





Заранее, большое спасибо за помощь!!!

Программист Dynamics AX, г. Санкт-Петербург

$
0
0
Компания, которая занимается разработкой web-решений для немецких и российских заказчиков, ищет Программиста Dynamics AX (г. Санкт-Петербург).

Основные задачи: разработка системы управления предприятием (совместный проект с немецкими партнёрами).
Сфера - ретейл, посылочные торговые фирмы.

Мы хотели бы от Вас следующих навыков:
  • Знания и опыт программирования в Dynamics AX (желательно - от 3-х лет)
  • Опыт с AX2012
  • Хорошие коммуникационные навыки.
  • English - минимум на уровне чтения и ведения переписки с Заказчиком

Рады предоставить комфортные условия работы:
- Оформление по ТК РФ
- Белая зарплата
- Соц. пакет, ДМС
- Коммуникация с зарубежными коллегами, совершенствование English
- Офис в центре Санкт-Петербурга
- Профессиональный и приветливый коллектив!

Если Вам интересно данное предложение, буду благодарна за обратную связь!

С уважением,
Вероника Лаврик
E-mail: veronika.lavrik@it-selection.ru
Skype: borisfen.september
Telegram: @veroni_ka (https://t.me/veroni_ka)

Different cost amount in ledger and inventory transactions of purchase invoice (AX 2012 R2 CU7)

$
0
0
Let us consider the case when the accounting currency is EUR and the purchase invoice currency is USD. Below is presented the list of the invoice lines. Assume that the exchange rate is 89,8069 EUR per 100 USD.
Код:

Product      Qty      Price    Amount, USD    Amount, EUR    Amount rounded, EUR

Product_1    5,00      40,00    200,00          179,6138            179,61

Product_2    5,00      56,00    280,00          251,4593            251,46

Product_3    25,00    100,00  2.500,00        2.245,1725          2.245,17

Product_4    25,00    120,00  3.000,00        2.694,2070          2.694,21

Product_5    50,00      30,00  1.500,00        1.347,1035          1.347,10

Invoice total                    7.480,00                            6.717,55

The rounded amount in EUR will be used as the cost amount in the inventory transaction. Thus the total inventory cost calculated basing on inventory transactions will be 6.717,55 EUR. And what about the cost amount posted into the General Ledger transaction? It will be calculated as a product of the invoice total amount in USD and the exchange rate, afterwards the result will be rounded to two decimal places. 7.480,00 * (89,8069 /100) = 6.717,5561 = 6.717,56

Continue reading

Программист (freelance), любой город, Columbus

$
0
0
Друзья, в РФ и не только, есть предложение: нужен разработчик на фриланс со знанием портала (Enterprise Portal) AX2012. Загурзка 100% на 2-3 месяца, работа по плановой оценке. Присылайте контакты в личку или на nama@columbusglobal.com

Mark Brummel: Invoking Azure Functions from AL in Visual Studio Code

Navigate Into Success: Invoking Azure Functions from AL recording available

$
0
0
Источник: http://vjeko.com/invoking-azure-func...ing-available/
==============

The “Invoking Azure Functions from AL using Visual Studio Code” webinar is over, and it was a pleasure delivering it for you, folks. There were 350+ people registered for it, and over 200+ people attended it. With those kinds of stats, who wouldn’t want to deliver more of these?

So, I can promise to prepare a couple of more Azure Functions from AL seminars, covering different kinds of topics, including handling binary data, XML, advanced JSON, and similar. Stay tuned.

In the meanwhile, if you didn’t have a chance to watch the session today in prime time, you can access it on YouTube: https://www.youtube.com/watch?v=Wp13...ature=youtu.be

Thanks to Mark and folks at NAV-Skills and Liberty Grove for making this possible.

Read this post at its original location at http://vjeko.com/invoking-azure-func...ing-available/, or visit the original blog at http://vjeko.com. 5e33c5f6cb90c441bd1f23d5b9eeca34The post Invoking Azure Functions from AL recording available appeared first on Vjeko.com.




Источник: http://vjeko.com/invoking-azure-func...ing-available/

i-neti: X ++ в AX7: Статические классы. Часть 8

$
0
0
Источник: http://i-neti.ru/blog/410
==============

Сейчас вы можете объявить класс как статический, используя ключевое слово static.

static class MyClass
{
}

В этом случае вы не сможете создать экземпляр класса. Это удобно для классов, которые содержат только статические методы – таких как класс Global.



подробнее



Источник: http://i-neti.ru/blog/410

Harish Mohanbabu: A deja vu feeling ..

$
0
0
Источник: https://harish-m.livejournal.com/31607.html
==============
A while back MFP in his own lucid and inimitable style published a series of 'Seeing is believing' posts on Microsoft Dynamics AX 2012. I book marked them so I can view them later at my leisure. But today when I went back I could not locate those posts. Particularly I could not find the following posts -
  • AX 2012 Developer Workspace
  • AX 2012 X++ Editor
  • AX 2012 Type Hierarchies
  • AX 2012 Creating an ISV Model
  • AX 2012 Uninstalling the Upgrade model
Where is it gone? I am confused now..



Addendum:
You are right Palle! I had the following note from MFP this evening -


I had to remove my posts due to potential disclosure of confidential information. I hope to be allowed to publish them again soon. I apologies for the inconvenience.

Thank you to Palle for stopping by; and thanks to MFP for Clarification!

==============
Источник: https://harish-m.livejournal.com/31607.html

Найти Table Relation для заданного поля таблицы

$
0
0
АХ 7

Допустим у меня есть TableId и FieldId, где FieldId - это поле на таблице с TableId
Это поле - foreign key на другую таблицу, и для этой связи существует Table relation на таблице с TableId

Как мне это определить наиболее оптимальным способом?

В смысле понять, есть такой relation, или нету

waldo: Add a logo to a C/AL Extension (ExtV1)

$
0
0
Источник: https://dynamicsuser.net/nav/b/waldo...xtension-extv1
==============

Just to set the right expectations – this blog is intended for Extensions Version 1. In other words, extensions that are:
  • developed completely in the well known classic C/SIDE development environment (C/AL).
  • created, installed and published with PowerShell
  • NOT created in VSCode
The “old” (in these times still “current”) stuff sort of speak ;-).

Why this blogpost?

Currently, we are still able to create Apps for Dynamics 365/AppSource in C/AL.

If we want to get it up to AppSource, a logo is mandatory.

I noticed that quite some people have problems with adding such a logo to the navx-file. And quite frankly, you can’t blame them. It’s not that clear.

Isn’t it just a matter to add it to the Manifest?

You would think so, wouldn’t you? Well, you are right, but it isn’t very straight forward. In PowerShell, you can’t simply add it to the manifest, because the manifest-cmdlets don’t have a “logo” parameter. You would expect one, but there isn’t one.

You would be able to change the “logo” attribute in the Manifest-xml-file. But what do you put there? I have seen people putting a URL there to some kind of web-storage that has the logo stored.

Well – no. No good either. As far as I know, the logo should be part of the extension itself.

So how do I add a logo to my extension then?

Let me explain you the way that I was able to get it to work.
  1. Make sure you have a local copy of the logo. Just don’t put it in the same directory as your delta files. You need to reference it separately. In my example, I just placed it in my working folder.

  2. Do not reference this logo in any manifest-cmdlet. Just create the Manifests without a logo (you won’t be able to do otherwise). But refer to this logo when you are building your NAVX with the New-NAVAppPackage cmdlet, like this:

New-NAVAppPackage ` -Path C:\_Workingfolder\TestLogo\MyApp.navx ` -Manifest (Get-NAVAppManifest C:\_Workingfolder\TestLogo\Manifest.xml) ` -SourcePath C:\_Workingfolder\TestLogo\AppFiles ` -Logo "C:\_Workingfolder\TestLogo\logo.png"That’s it.

How to test if everything is correct?

I see two ways to test this.

You can test the manifest of the navx file. May be some don’t know, but you can apply the “Get-NAVAppManifest” to a navx as well, like:

Get-NAVAppManifest -Path "C:\_Workingfolder\TestLogo\MyApp.navx"You’ll see an output like this:



And you can see the “AppLogo” has been filled in. So in the resulting manifest, you do have the logo! I can only assume the logo was added to the navx as well.

Another way to test this, is obviously in the web client, where you can actually see the logo in the “Extension Management” page, like you can see here:



I hope this helps you in your quest to get your app certified for AppSource and Dynamics 365 !




Источник: https://dynamicsuser.net/nav/b/waldo...xtension-extv1

Роль безопасности для редактирования 1 сущности

$
0
0
Добрый день.
CRM 2011.
Возник следующий вопрос/необходимость/пожелания:
можно ли завести в системе Роль безопасности, которая давала бы права на кастомизаю одной и только одной сущности? Т.е. предлагается, что у нас в системе будет несколько пользователей с ролью безопасности, которые смогут создавать новые формы у сущности, поля, представления и т.д., но только лишь с одной сущностью, которая будет отдана им на откуп.
Возможно ли такое реализовать и, если подскажете, что почитать на эту тему, буду очень признателен.

axcoder: New cloud architecture guides

Viewing all 14626 articles
Browse latest View live