Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics AX (Archived)

Validation rules

Posted on by Microsoft Employee

Hi,

This is what I am looking at (MS2012).

I am to create a validation rule to the product and create some maintenance form for these rules.

I am using cases for this.

It is ok having like a query where you can "filter" the different table-fields, but how do I create and use this in like a "Validate" button from release products? Maintenance by admin for the "filters".

I have added a new record to table EngChgCaseCategoryRule and connected this to a new

case process and category in validation rules and this works fine. The question is how to use it and create/modify rules for this.

I am thinking something like this.

1. Lookup table for tables (how can I get all tables to select from in a drop-down list?).

2. Lookup table for fields (how can I connect this to my lookup table for tables and get a list of fields for the tables?).

3. Validate table where I connect tables and fields from my 2 lookup tables.

4. Make a query from the Validate table where I can set the conditions (if table1.field1 = "A" and table1.field2 != "4" and table2.field1 = "100" or table1.field1 = "B"...).

5. Use this "query" on buttons from different forms (released product etc.) like a check if the settings for this product is ok.

Have someone done something similar?

/Fredrik.

*This post is locked for comments

  • jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    You are welcome. :)

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Validation rules

    Yes, it worked.

    Thanks :)

    /Fredrik.

  • Verified answer
    jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    Did you manage to get it working ?

  • jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    I tried making an info command in the code that I tested with and it does not work.

    The other thing you should consider when putting text into the code field, is that it must be be something that the xppCompiler is able to compile:

    Try this:

    boolean evaluate()

    {

      InventTable inventTable = InventTable::find("%1");

      If (InventTable.ItemType == ItemType::Item)

      {

          return true;

      }

      else

      {

          return false;

      }

    }

    This code implements a function that return a boolean. It takes an argument in %1 which is used for finding the right inventtable record.

    The argument is passed when the doTraverse method does:

    code = strFmt(_T_TableFields.Code,common.(fieldNum(InventTable,ItemId)));

    This pulls out the ItemId from the common tablebuffer and strfmt puts it in to code.

    Now if the common tablebuffer contains the InventTable for itemid 1014, then

    the code that the xppcompiler gets is:

    boolean evaluate()

    {

      InventTable inventTable = InventTable::find("1014");

      If (InventTable.ItemType == ItemType::Item)

      {

          return true;

      }

      else

      {

          return false;

      }

    }

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Validation rules

    Hi,

    I imported the project.

    Right now I am struggling with the syntax for the code.

    I get an Error:

    Code in table T_TableFields can't compile. *** Error: -1, Syntax error.. Code:

    info("hej");return true;

    /Fredrik.

  • jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    I have made the code and have been able to run it on an AX2012 R2.
    Have you fetched the .xpo-file I shared and imported it ?

    What version are you running ?

    Also when you want to be able to run code that generates and runs code, the user running this MUST have development rights as you are actually telling the system to compile some code and run it.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Validation rules

    Hi and thanks,

    Item 100 and value was just an example, it could be anything.

    I got 2 errors:

    Request for the permission of type 'ExecutePermission' failed.

    (S)\Classes\ExecutePermission\demand

    (S)\Classes\XppCompiler\new

    (S)\Classes\Traverser\doTraverse - line 24

    (S)\Classes\Traverser\run - line 10

    (S)\Classes\Traverser\main - line 8

    and

    XppCompiler object not initialized.

    Stack trace

    (S)\Classes\Traverser\doTraverse - line 33

    (S)\Classes\Traverser\run - line 10

    (S)\Classes\Traverser\main - line 8

    /Fredrik.

  • jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    Be aware that using xppCompiler is a dangerous API, and that you should be extremely restrictive about what goes in the code field in you T_TableFields table, IF you expose the field in an UI.

    Otherwise you could implement some sort of scanner to scan the code for commands that does data manipulation in the database and refuse to execute that code.

  • Suggested answer
    jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    The link should have been:

    http://1drv.ms/1LAetN6

    :)

  • Suggested answer
    jasman Profile Picture
    jasman 1,411 on at
    RE: Validation rules

    Make one class:

    class Traverser

    {

       ExecutePermission       perm;

    }

    private void doTraverse(T_TableFields   _T_TableFields)

    {

       Query                   q;

       QueryBuildDataSource    qbds;

       QueryRun                qr;

       Common                  common;

       XppCompiler             xppCompiler;

       str                     code    =   @"%1";

       boolean                 evalResult;

       // Constrcut query

       q = new Query();

       qbds = SysQuery::findOrCreateDataSource(q,_T_TableFields._TableId);

       SysQuery::findOrCreateRange(qbds,_T_TableFields._FieldId).value(this.relationalOperator(_T_TableFields.Operator)+_T_TableFields.Value);

       // And run query

       qr = new QueryRun(q);

       while (qr.next())

       {

           common = qr.get(_T_TableFields._TableId);

           if (_T_TableFields.Code)

           {

               xppCompiler = new XppCompiler();

               code = strFmt(_T_TableFields.Code,common.(fieldNum(InventTable,ItemId)));

               if (xppCompiler && xppCompiler.compile(code))

               {

                   evalResult = xppCompiler.executeEx();

                   if (evalResult)

                       info(strFmt("Table: %1, field: %2, fieldvalue: %3 OK!",common.TableId,common.RecId,common.(_T_TableFields._FieldId)));

               }

               else

                   throw error(strFmt("Code in table T_TableFields can't compile. %1. Code:\n%2",xppCompiler.errorText(),code));

           }

       }

    }

    public void run()

    {

       T_TableFields   t_tableFields;

       perm = new ExecutePermission();

       if (perm != null)

       {

           while select t_tableFields

           {

               this.doTraverse(T_TableFields);

           }

       }

       CodeAccessPermission::revertAssert();

    }

    public static void main(Args _args)

    {

       Traverser   traverser;

       traverser = new traverser();

       if (traverser)

       {

           traverser.run();

       }

    }

    private str relationalOperator(str _op)

    {

       switch(_op)

       {

           case    "EQ"    :  return "==";

           case    "NEQ"   :  return "!=";

           case    "GT"    :  return ">";

           case    "LT"    :  return "<";

       }

       return "==";

    }

    The table

    T-TableFields

    have the fields you mention where

    _FieldId is integer and contains 2

    _TableId is integer and contains 175

    Code is memo-type

    Operator is string and contains "NEQ"

    Value is string and contains "10"

    Code contains the code:

    boolean evaluate()

    {

       InventTable inventTable = InventTable::find("%1");

       If (InventTable.ItemType == ItemType::Item)

       {

           return true;

       }

       else

       {

           return false;

       }

    }

    Or get the code here:

    onedrive.live.com/redir;authkey=!AMe53BC6_9FE_KE&ithint=folder%2cxpo

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,269 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,198 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans