web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

Form Data Source Validation (validatedWrite)

(0) ShareShare
ReportReport
Posted on by 384

Dear gents,

I am trying to create a new validation on SalesAgreement Form, my requirement is when the user enters a price not valid in Trade Agreement Journal (PriceDiscTable) the form will return an error/Check failed.

i was able to create such validation on the table AgreementLineQuantityCommitment, since the field name is PricePerUnit on this table.

but im facing an issue, when the user insert an invalid line, he receives the error. but when he duplicates the Tab on browser or close the browser and open it again, the line is automatically saved on line despite that it shouldn't since the price is not valid.

then i tried the below code which is the validation on formDatasource and not directly on the table, and the record is still showing after closing/duplicating the form.

 [FormDataSourceEventHandler(formDataSourceStr(SalesAgreement, ALine), FormDataSourceEventType::ValidatingWrite)]
    public static void abTable_OnValidatingWrite(FormDataSource sender, FormDataSourceEventArgs e)
    {
        FormDataSource AgreementLineQuantityCommitmentDS  =sender as FormDataSource;
        AgreementLineQuantityCommitment AgreementLineQuantityCommitment = AgreementLineQuantityCommitmentDS.cursor();
        AgreementHeader AgreementHeader,AgreementHeader1;
        AgreementLine AgreementLine,AgreementLine1;
            AgreementHeaderDefault AgreementHeaderDefault,AgreementHeaderDefault1;
            PriceDiscAdmTrans  PriceDiscAdmTrans ;
            PriceDiscTable PriceDiscTable,PriceDiscTable1;

        boolean docancel;
        var args = e as FormDataSourceCancelEventArgs;

        select AgreementLine1 where AgreementLineQuantityCommitment.RecId == AgreementLine1.RecId;
            select AgreementHeader1 where AgreementHeader1.Recid == AgreementLine1.Agreement;
            select AgreementHeaderDefault1 where AgreementHeaderDefault1.AgreementHeader ==AgreementHeader1.RecId;
            if(AgreementHeader1.IS_Approved ==NoYes::No)
            {
                if(AgreementHeaderDefault1.IS_PriceGroup)
                {
                    select PriceDiscTable
                          where AgreementLineQuantityCommitment.ItemId ==PriceDiscTable.ItemRelation
                       
                         join AgreementLine where AgreementLineQuantityCommitment.RecId == AgreementLine.RecId
                           join AgreementHeader where AgreementHeader.Recid == AgreementLine.Agreement
                           && AgreementHeader.DefaultAgreementLineEffectiveDate >=PriceDiscTable.FromDate
                        && AgreementHeader.DefaultAgreementLineEffectiveDate <= PriceDiscTable.ToDate
                          join AgreementHeaderDefault where AgreementHeaderDefault.AgreementHeader ==AgreementHeader.RecId
                          && AgreementHeaderDefault.IS_PriceGroup ==PriceDiscTable.AccountRelation ;

                
                    if(PriceDiscTable)
                    {
                        if(AgreementLineQuantityCommitment.PricePerUnit 

your help is highly appreciated, as it's an urgent case.

Regards,

I have the same question (0)
  • WillWU Profile Picture
    22,363 on at

    Hi sylvesterPowerBi,

    Please try to copy “onValidating” event from Form Datasource field and write your code there:

       [FormDataFieldEventHandler(formDataFieldStr(SalesTable, SalesLine, SalesPrice), FormDataFieldEventType::Validating)]
        public static void SalesPrice_OnValidating(FormDataObject sender, FormDataFieldEventArgs e)
        {
      
        }
        

  • Martin Dráb Profile Picture
    237,990 Most Valuable Professional on at

    Your code looked a bit confusing to me, therefore I refactored it a little:

    [FormDataSourceEventHandler(formDataSourceStr(SalesAgreement, ALine), FormDataSourceEventType::ValidatingWrite)]
    public static void abTable_OnValidatingWrite(FormDataSource sender, FormDataSourceEventArgs e)
    {
    	var args = e as FormDataSourceCancelEventArgs;
    	
    	FormDataSource commitmentDs = sender as FormDataSource;
    	AgreementLineQuantityCommitment commitment = commitmentDs.cursor() as AgreementLineQuantityCommitment;
    
    	if (!commitment)
    	{
    		return;
    	}
    	
    	AgreementHeader agreementHeader1;
    	AgreementLine agreementLine1;
    	AgreementHeaderDefault agreementHeaderDefault1;
    	
    	select RecId from agreementHeader1
    		exists join agreementLine1
    			where agreementLine1.Agreement == agreementHeader1.RecId
    			   && agreementLine1.RecId == commitment.RecId
    		exists join agreementHeaderDefault1
    			where agreementHeaderDefault1.AgreementHeader == agreementHeader1.RecId;
    			   && agreementHeaderDefault1.IS_PriceGroup
    
    	if (agreementHeader1.RecId)
    	{
    		PriceDiscTable priceDiscTable;
    		AgreementHeader agreementHeader;
    		AgreementLine agreementLine;
    		
    		select priceDiscTable
    			where priceDiscTable.ItemRelation == commitment.ItemId
    			join agreementLine
    				where agreementLine.RecId == commitment.RecId 
    			join agreementHeader
    				where agreementHeader.RecId == agreementLine.Agreement
    				   && agreementHeader.DefaultAgreementLineEffectiveDate >= priceDiscTable.FromDate
    				   && agreementHeader.DefaultAgreementLineEffectiveDate <= priceDiscTable.ToDate
    			join agreementHeaderDefault
    				where agreementHeaderDefault.AgreementHeader == agreementHeader.RecId
    				   && agreementHeaderDefault.IS_PriceGroup == priceDiscTable.AccountRelation;
    	
    		if (priceDiscTable)
    		{
    			if (commitment.PricePerUnit < priceDiscTable.Amount)
    			{
    				warning("Unit Price is Not within current valid price range");
    				args.cancel(true);
    
    			}
    			else
    			{
    				info("Price Range Accepted");
    
    			}
    		}
    		else
    		{
    			warning("No Trade Agreement Available.");
    			args.cancel(true);
    		}	
    	}
    }

    It seems that it can be done on table, therefore I would prefer doing it there. What if you put a breakpoint to insert() and review where it's called from?

  • Suggested answer
    nmaenpaa Profile Picture
    101,166 Moderator on at

    First of all, I recommend implementing your logic in the underlying table. This way the validation kicks in always when data is created, not only on this particular form. Right now it might not seem relevant to you but if you want to ensure data quality in the system, it's important to put your validations in optimal place.

    Second, if you want to fail the validation, you must set return value of the event args to false by calling e.setReturnValue(false). Forget the FormDataSourceCancelEventArgs. You don't want to cancel anything, you want to pass your validation result back to the standard process.

  • sylvesterPowerBi Profile Picture
    384 on at

    Hi nikolaos,

    so you suggest to change my code from FormDataSource validation to the below :

    [DataEventHandler(tableStr(AgreementLineQuantityCommitment), DataEventType::ValidatedWrite)]
     public static  void AgreementLineQuantityCommitment_onValidatedWrite(Common sender, DataEventArgs e)
     {
     // validation here is working fine, until i close the form or duplicate that tab.
     }

    [quote

    First of all, I recommend implementing your logic in the underlying table. This way the validation kicks in always when data is created, not only on this particular form. Right now it might not seem relevant to you but if you want to ensure data quality in the system, it's important to put your validations in optimal place.

    Second, if you want to fail the validation, you must set return value of the event args to false by calling e.setReturnValue(false). Forget the FormDataSourceCancelEventArgs. You don't want to cancel anything, you want to pass your validation result back to the standard process.

    [/quote
  • Suggested answer
    nmaenpaa Profile Picture
    101,166 Moderator on at

    Yes, that is correct. You also seem to have changed the event type from ValidatingWrite to ValidatedWrite. This will impact if your validations run before or after the standard validations.

    But in either case, you must send the "false" return value from your code in order for it to work correctly.

  • sylvesterPowerBi Profile Picture
    384 on at

    Dear Nikolaos,

    i tried to add the below error :

    e.setReturnValue(false), but i received an error saying : ClassDoesNotContainMethod: Class 'DataEventArgs' does not contain a definition for method 'setReturnValue' and no extension method 'setReturnValue' accepting a first argument of type 'DataEventArgs' is found on any extension class.

    please find my code below.

     [DataEventHandler(tableStr(AgreementLineQuantityCommitment), DataEventType::ValidatingWrite)]
        public static  void AgreementLineQuantityCommitment_onValidatedWrite(Common sender, DataEventArgs e)
        {
            AgreementLineQuantityCommitment AgreementLineQuantityCommitment = sender ;//as AgreementLineQuantityCommitment;
            AgreementHeader AgreementHeader,AgreementHeader1;
            AgreementLine AgreementLine,AgreementLine1;
            AgreementHeaderDefault AgreementHeaderDefault,AgreementHeaderDefault1;
            PriceDiscAdmTrans  PriceDiscAdmTrans ;
            PriceDiscTable PriceDiscTable,PriceDiscTable1;
            SalesAgreementHeader SalesAgreementHeader;
            ValidateEventArgs validateEventArgs = e as ValidateEventArgs ;
            boolean ret = validateEventArgs.parmValidateResult();
            str item,item1,sq,s1;
            int recid,recid1;
    
    
            if(AgreementLineQuantityCommitment)
            {
                select AgreementLine1 where AgreementLineQuantityCommitment.RecId == AgreementLine1.RecId;
                select AgreementHeader1 where AgreementHeader1.Recid == AgreementLine1.Agreement;
                select AgreementHeaderDefault1 where AgreementHeaderDefault1.AgreementHeader ==AgreementHeader1.RecId;
    
    
    
    
                if(AgreementHeader1.IS_Approved ==NoYes::No)
                {
                    if(AgreementHeaderDefault1.IS_PriceGroup)
                    {
                        select PriceDiscTable
                          where AgreementLineQuantityCommitment.ItemId ==PriceDiscTable.ItemRelation
                          && AgreementLineQuantityCommitment.ExpirationDate >=PriceDiscTable.FromDate
                         && AgreementLineQuantityCommitment.ExpirationDate <= PriceDiscTable.ToDate
                         join AgreementLine where AgreementLineQuantityCommitment.RecId == AgreementLine.RecId
                           join AgreementHeader where AgreementHeader.Recid == AgreementLine.Agreement
                           && AgreementHeader.DefaultAgreementLineEffectiveDate >=PriceDiscTable.FromDate
                        && AgreementHeader.DefaultAgreementLineEffectiveDate <= PriceDiscTable.ToDate
                          join AgreementHeaderDefault where AgreementHeaderDefault.AgreementHeader ==AgreementHeader.RecId
                          && AgreementHeaderDefault.IS_PriceGroup ==PriceDiscTable.AccountRelation ;
    
                         //trade agreement
                        if(PriceDiscTable)
                        {
                            if(AgreementLineQuantityCommitment.PricePerUnit 

    thank you for your help.

  • nmaenpaa Profile Picture
    101,166 Moderator on at

    Ah, you are right, the correct method to use is parmValidateResult (which you seem to have found already).

    So, is it working now?

  • sylvesterPowerBi Profile Picture
    384 on at

    The validation is working, but if i insert a line with a not valid price, i validate,  i receive the error, then i duplicate the browser tab or i close the browser then i re-open it again, i find the line saved on the sales agreement, but it shouldn't. how can i disallow the form to save the record when the validation is wrong ?

  • Suggested answer
    nmaenpaa Profile Picture
    101,166 Moderator on at

    That is not expected to happen. The validateWrite prevents inserting data that fails the validations.

    Are you absolutely sure that the same record that failed validation is saved in the table? Are you sure it's not some old record that you created before your validation code was working?

    This simple code demonstrates that if you return false in the validation event, the data can't be saved. Try to implement this code, and see if you can create new customer group records. You should not be able to do that. Once you see that it works, you can begin to investigate what exactly happens in your scenario.

        [DataEventHandler(tableStr(CustGroup), DataEventType::ValidatingWrite)]
        public static void CustGroup_onValidatingWrite(Common sender, DataEventArgs e)
        {
            ValidateEventArgs validateEventArgs = e as ValidateEventArgs ;
    
            validateEventArgs.parmValidateResult(false);
            info("false");
        }

  • sylvesterPowerBi Profile Picture
    384 on at

    Dear martin,

    [quote]

    Your code looked a bit confusing to me, therefore I refactored it a little:

    Fullscreen
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    if (!commitment)
    {
    return;
    }
    AgreementHeader agreementHeader1;
    AgreementLine agreementLine1;
    AgreementHeaderDefault agreementHeaderDefault1;
    select RecId from agreementHeader1
    exists join agreementLine1
    where agreementLine1.Agreement == agreementHeader1.RecId
    && agreementLine1.RecId == commitment.RecId
    exists join agreementHeaderDefault1
    where agreementHeaderDefault1.AgreementHeader == agreementHeader1.RecId;
    && agreementHeaderDefault1.IS_PriceGroup
    if (agreementHeader1.RecId)
    {
    PriceDiscTable priceDiscTable;
    AgreementHeader agreementHeader;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    It seems that it can be done on table, therefore I would prefer doing it there. What if you put a breakpoint to insert() and review where it's called from?

    [/quote]

    i tried your code, it is validating but when i duplicate the browser tab or close the browser and open it again, i still can see my line, which is not supposed to.

    your help is highly appreciated.

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

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Abhilash Warrier Profile Picture

Abhilash Warrier 669 Super User 2025 Season 2

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 449 Super User 2025 Season 2

#3
Martin Dráb Profile Picture

Martin Dráb 384 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans