The M-Files Community will be updated on Tuesday, April 2, 2024 at 10:00 AM EST / 2:00 PM GMT and the update is expected to last for several hours. The site will be unavailable during this time.

This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I can't make the custom validator example work

Hello,

I am developing a VAF2.3 application where I need to make an ODBC connection; So I want a configuration tab in the admin to write the connection string and then validate it. That's exactly the example here : Custom-Validation .

Here are the 2 class I made: 

Configuration.cs :

using MFiles.VAF.Configuration;
using System.Runtime.Serialization;
using System.Collections.Generic;

namespace mynamespace
{
    [DataContract]
    public class Configuration : MFiles.VAF.Extensions.Configuration.ConfigurationBase
    {

        [DataMember]
        [JsonConfEditor(DefaultValue = "v_agents_responsables_h",
        Label = "Nom de la table",
        HelpText = "Nom de la table ou de la vue contenant le référentiel Agents")]
        public string tablename = "";

        [DataMember]
        [JsonConfEditor(DefaultValue = "Driver={SQL Server};Server=mf-sql.mydomain.local;Database=REF AGENTS;Uid=sa;Pwd=Admin123;",
            Label = "Chaîne de connexion ODBC",
            HelpText = "La connectionString ODBC permettant de se connecter au référentiel Agents. Elle doit faire référence à la connexion TNS créée lors de l'installation du serveur")]
        public string ConnectionString = "Driver={SQL Server};Server=mf-sql.mydomain.local;Database=REF AGENTS;Uid=sa;Pwd=Admin123;";

        [DataMember]
        public List<Mapping> mappings { get; set; }

        [DataContract]
        public class Mapping
        {
            [DataMember]
            public string colonneSQL { get; set; }

            [DataMember]
            [TextEditor(IsRequired = true)]
            public string mfilesProperty { get; set; }
        }
    }


}

VaultApplication.cs: 

using MFiles.VAF.Common;
using MFiles.VAF.Configuration;
using MFilesAPI;
using System;
using System.Collections;
using System.Collections.Generic;
using MFiles.VaultApplications.Logging;


namespace mynamespace
{
    /// <summary>
    /// The entry point for this Vault Application Framework application.
    /// </summary>
    /// <remarks>Examples and further information available on the developer portal: http://developer.m-files.com/. </remarks>
    public class VaultApplication
        : MFiles.VAF.Extensions.ConfigurableVaultApplicationBase<Configuration>
    {

        #region Overrides of ConfigurableVaultApplicationBase<Configuration>

        /// <inheritdoc />
        protected override IEnumerable<ValidationFinding> CustomValidation(Vault vault, Configuration config)
        {
            return base.CustomValidation(vault, config);
        }


        private IEnumerable<ValidationFinding> CustomValidator(Configuration configuration)
        {
            ValidationFinding finding = null;

            try
            {
                // Connect to the database to test the connection is valid.
                using (var sqlConnection = new System.Data.SqlClient.SqlConnection(configuration.ConnectionString))
                {
                    // Connect to the database.
                    sqlConnection.Open();

                    // If no exception then report okay.
                    finding = new ValidationFinding(
                        ValidationFindingType.Ok,
                        nameof(Configuration.ConnectionString),
                        "Connection successful");

                    // Disconnect.
                    sqlConnection.Close();
                }
            }
            catch (Exception e)
            {
                // Report an exception.
                finding = new ValidationFinding(
                    ValidationFindingType.Error,
                    nameof(Configuration.ConnectionString),
                    $"Exception connecting to server: {e.Message}");
            }

            // Return the finding.
            yield return finding;
        }

        #endregion

// my custom code

}}

In the admin interface, I can write anything but it will never be validated: 

I don't really understand the example. Which code do I need to conserve in the 2.3 framework?

 Thank you all for the help.

Amaury

NB : here are the librairies : 

  • At the bottom of the screen there are tabs for "local" and "server".  Does "server" show a red icon?

  • Hang on, in your example you override the CustomValidation method (correct), but you never actually call your CustomValidator method.  Your validation that you've written never gets called/used.

    You need to return whatever base.CustomValidation returns, but also call your validation.  Something like this:

            /// <inheritdoc />
            protected override IEnumerable<ValidationFinding> CustomValidation(Vault vault, Configuration config)
            {
                foreach(var f in base.CustomValidation(vault, config))
                    yield return f;
                foreach(var f in this.CustomValidator(config))
                    yield return f;
            }

  • I copied/pasted your code and i works perfectly now. But I have to admit that I don't understand why... Moreover, it doesn't look like what is described in the example webpage.

    Again, thank you for the help Craig.

  • Which bit don't you understand?  I'll try to help if I can.

    The basic concept is that the CustomValidation method must return all validation findings; everything which should be highlighted in the "Server" section on the configuration screen.

    In the code sample you initially provided, the method simply returned the rules returned by the VAF itself.  It literally just returned the base implementation.  Whilst you declared a method that also returned validation findings, it was not called by anything so was never run.

    In the code sample I gave I altered the code so that it returns any findings from the base code, then calls your CustomValidator method and returns findings found by that.  That's all it does; just calls your code and makes sure that your findings are returned along with any of the base ones.

    I agree that the example could be more clear; I'll try to find some time to improve that.

  • I think I understand now. I should probably look more in details what is the base class we inherit from