Segui

Tutorial C#: come inserire il documento Dipendenti di Perfetto4

Sommario

Questo tutorial è rivolto a sviluppatori .NET che devono integrare applicazioni esterne con Perfetto4 tramite Web Service SOAP. È richiesta una conoscenza base di C#, Windows Forms e XML.

Nell'articolo sono descritti i passi da seguire per poter creare un esempio di un'applicazione scritta in linguaggio C# che consente di effettuare l'autenticazione al prodotto Perfetto4 e l'inserimento del documento, utilizzando la tecnologia Magic Link.

Per facilitare la lettura dell'articolo di seguito un indice delle sezioni dell'articolo:


Creazione del progetto

  • aprire "Visual Studio", in questo esempio è stato utilizzato Visual Studio 2022;
  • selezionare "Nuovo progetto...";
  • scegliere "Applicazione Windows Form";
  • inserire il nome del progetto, in questo caso: "ExampleProject_Utility_CS".

Creazione della maschera di Login e inserimento del dipendente

Nel seguente sezione è mostrato come creare l'interfaccia grafica dell'applicazione. Essa è divisa in due parti, una rivolta alla gestione dell'autenticazione e una con una tab dedicata all'inserimento del documento.

I passi da seguire per realizzare l'interfaccia sono:

  • Inserire i campi relativi alla fase di login:

    Login.png
    Schermata di "Login"
  • Inserire i campi relativi alla fase di inserimento del dipendente:

    Insert.png
    Schermata dell'inserimento del "Tecnico"

Connessione ai Web Service di Perfetto4

Per poter accedere ai metodi web che consentono all'utente di registrarsi e inserire i dati in Perfetto4, è necessario aggiungere i riferimenti ai servizi di Perfetto4.

Le operazioni da seguire per aggiungere un riferimento ad un servizio sono le seguenti:

  • posizionarsi sul nodo del progetto dell'albero dell'"Esplora soluzioni";
  • fare click con il tasto destro del mouse;
  • selezionare la voce "Aggiungi riferimento al servizio";
  • selezionare la voce "WCF Web Service" e procedere;
  • procedere lasciando le opzioni di default come nello screenshot seguente;
4.png
  • inserire il percorso del Web Service ed effettuare l'individuazione del servizio per avere una conferma;
  • scegliere un Namespace per il servizio che stiamo aggiungendo;
  • finalizzare l'aggiunta del servizio premendo Avanti;
1.png

Per l'esempio è necessario inserire il riferimento per LoginManager e TbServices.

Una volta inseriti i riferimenti ai Web Service è necessario creare una loro istanza nel seguente modo:

Esempio C#: esempio di instanziazione dei client dei servizi

 AppSession.BaseUrl = $"{protocol.Trim()}://{server.Trim()}:{port.Trim()}/{instance.Trim()}"; // Nella Solution i valori vengono presi dalla schermata di Login iniziale
 
 using var loginManagerClient = new MicroareaLoginManagerSoapClient(
                      MicroareaLoginManagerSoapClient.EndpointConfiguration.MicroareaLoginManagerSoap,
                      $"{AppSession.BaseUrl.TrimEnd('/')}/LoginManager/LoginManager.asmx");
 
 using var tbServicesClient = new TbServicesSoapClient(
                      TbServicesSoapClient.EndpointConfiguration.TbServicesSoap,
                      $"{AppSession.BaseUrl.TrimEnd('/')}/TbServices/TbServices.asmx");

Autenticazione

Per effettuare l'autenticazione al sistema è utilizzato il metodo web LoginCompact del LoginManager.

Nel seguente snippet di codice è mostrato come recuperare i valori dei campi relativi alla login e passare tali valori al metodo LoginCompact per ottenere il codice di autenticazione:

Esempio C#: logica di connessione al server e login ad un'azienda

//--------------------------------------------------------------------------
private async void buttonConnect_Click(object? sender, EventArgs e)
{
    string protocol = comboBoxProtocol.SelectedItem?.ToString() ?? "http";
    string server = textBoxServer.Text;
    string port = string.IsNullOrWhiteSpace(textBoxPort.Text) ? "80" : textBoxPort.Text;
    string instance = textBoxInstanceFolder.Text;

    toolStripStatusLoginConnectedColor.BackColor = Color.Orange;
    toolStripStatusLoginConnectedLabel.Text = "Connecting...";
    Cursor.Current = Cursors.WaitCursor;

    var result = await _connectionService.TestConnectionAsync(protocol, server, port, instance);

    if (result.Success)
    {
        AppSession.BaseUrl = $"{protocol.Trim()}://{server.Trim()}:{port.Trim()}/{instance.Trim()}";
        groupBoxLogin.Enabled = true;
        LoadCompanies(false);

        Cursor.Current = Cursors.Default;
        toolStripStatusLoginConnectedColor.BackColor = Color.Green;
        toolStripStatusLoginConnectedLabel.Text = "Connected    ";
        MessageBox.Show(result.Message, "Connected    ", MessageBoxButtons.OK, MessageBoxIcon.Information);

        groupBoxConnection.Enabled = false;
        buttonDisconnect.Enabled = true;
    }
    else
    {
        groupBoxLogin.Enabled = false;
        Cursor.Current = Cursors.Default;
        MessageBox.Show(result.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

//--------------------------------------------------------------------------
private void buttonLogin_Click(object? sender, EventArgs e)
{
    Cursor.Current = Cursors.WaitCursor;

    if (!groupBoxLogin.Enabled)
    {
        MessageBox.Show("Connect first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    if (string.IsNullOrWhiteSpace(textBoxUser.Text) || string.IsNullOrWhiteSpace(textBoxPwd.Text))
    {
        MessageBox.Show("Username and password are required.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    AppSession.Username = textBoxUser.Text.Trim();
    Password = textBoxPwd.Text.Trim();
    AppSession.ProducerKey = textBoxProducerKey.Text.Trim();

    if (!PerformLogin())
        return;

    Cursor.Current = Cursors.Default;

    DialogResult = DialogResult.OK;
    Close();
}

//--------------------------------------------------------------------------
private bool PerformLogin()
{
    string authToken = string.Empty;
    if (string.IsNullOrEmpty(textBoxUser.Text) || string.IsNullOrEmpty(comboBoxCompany.Text))
    {
        MessageBox.Show("Select a company.");
        return false;
    }

    string user = textBoxUser.Text;
    string company = comboBoxCompany.Text;

    using var client = new MicroareaLoginManagerSoapClient(
        MicroareaLoginManagerSoapClient.EndpointConfiguration.MicroareaLoginManagerSoap,
        $"{AppSession.BaseUrl.TrimEnd('/')}/LoginManager/LoginManager.asmx");

    int result = client.LoginCompact(ref user, ref company, Password, AppSession.ProducerKey, false, out authToken);

    if (result == 14)
    {
        var force = MessageBox.Show(
            "Session already exists. Do you want to force the login?",
            "Simultaneous login",
            MessageBoxButtons.YesNo,
            MessageBoxIcon.Warning);

        if (force == DialogResult.Yes)
        {
            result = client.LoginCompact(ref user, ref company, Password, AppSession.ProducerKey, true, out authToken);
        }
    }

    if (result == 0)
    {
        AppSession.AuthenticationToken = authToken;
        AppSession.Company = company;
        AppSession.Username = textBoxUser.Text;
        AppSession.ProducerKey = textBoxProducerKey.Text.Trim();
        return true;
    }

    MessageBox.Show($"Failed login. Code: {result}", "Login Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
    return false;
}

Se la fase di autenticazione va a buon fine viene salvato il codice di autenticazione.


Invio dati dipendente a Perfetto4

Per inviare a Perfetto4 i dati di un documento si deve utilizzare il metodo SetData del Web Service TbService e passare ad esso una stringa xml, formattata secondo il profilo di esportazione, contenente i dati del documento.

Nel codice seguente è mostrato come creare la stringa xml dei dati da inviare, come invocare il metodo SetData impostando i parametri in modo corretto e come mostrare il parametro di output del metodo.
In questo specifico esempio è stato anche implementato un semplice Trace per tenere traccia degli step eseguiti dal metodo:

Esempio C#: esempio di inserimento dati nell'anagrafica di un Tecnico

//--------------------------------------------------------------------------
private void buttonInsert_Click(object? sender, EventArgs e)
{
    if ((string.IsNullOrWhiteSpace(textBoxCode.Text)) ||
        (textBoxCode.Text.Length > 21))
    {
        MessageBox.Show("Please enter a valid code for the employee.");
        return;
    }

    string aXMLData = "<?xml version=\"1.0\"?>" +
                            "<maxs:Employees xmlns:maxs=\"http://www.microarea.it/Schema/2004/Smart/Perfetto/PCore/Employees/Standard/Default.xsd\" tbNamespace=\"Document.Perfetto.PCore.Documents.Employees\" xTechProfile=\"Default\">" +
                                "<maxs:Data>" +
                                "<maxs:Employees master=\"true\">" +
                                    "<maxs:Employee>" + System.Security.SecurityElement.Escape(textBoxCode.Text) + "</maxs:Employee>" +
                                    "<maxs:Name>" + System.Security.SecurityElement.Escape(textBoxName.Text) + "</maxs:Name>" +
                                    "<maxs:Address>" + System.Security.SecurityElement.Escape(textBoxAddress.Text) + "</maxs:Address>" +
                                    "<maxs:City>" + System.Security.SecurityElement.Escape(textBoxCity.Text) + "</maxs:City>" +
                                    "<maxs:ZipCode>" + System.Security.SecurityElement.Escape(textBoxZipCode.Text) + "</maxs:ZipCode>" +
                                    "<maxs:Telephone1>" + System.Security.SecurityElement.Escape(textBoxTelephone.Text) + "</maxs:Telephone1>" +
                                "</maxs:Employees>" +
                                "</maxs:Data>" +
                            "</maxs:Employees>";
    string aResult = string.Empty;

    try
    {
        DateTime applicationDate = DateTime.Now;
        string tbServicesUrl = $"{AppSession.BaseUrl.TrimEnd('/')}/TbServices/TbServices.asmx";

        AppendLog("--------------------------------------------------");
        AppendLog($"Starting SetData transaction on {tbServicesUrl}");
        AppendLog($"Request XML:\n{aXMLData}");

        using var client = new TbServicesSoapClient(
            TbServicesSoapClient.EndpointConfiguration.TbServicesSoap,
            tbServicesUrl);


        Stopwatch sw = Stopwatch.StartNew();
        bool success = client.SetData(AppSession.AuthenticationToken, aXMLData, applicationDate, 0, false, out aResult);
        sw.Stop();

        AppendLog($"Transaction completed in {sw.ElapsedMilliseconds} ms.");
        AppendLog($"Response XML:\n{aResult}");

        if (success)
        {
            if (string.IsNullOrWhiteSpace(aResult))
            {
                AppendLog("WARNING: Employee inserted, but no XML details were returned by the service.");
                MessageBox.Show("Employee inserted, but no XML details were returned by the service.");
            }
            else
            {

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(aResult);
                XmlNamespaceManager xmlNsManager = new XmlNamespaceManager(doc.NameTable);
                xmlNsManager.AddNamespace(doc.DocumentElement.Prefix, doc.DocumentElement.NamespaceURI);
                XmlNode emplNode = doc.SelectSingleNode("//maxs:Employees//maxs:Data//maxs:Employees//maxs:Employee", xmlNsManager);

                string postedEmployeeCode = emplNode?.InnerText ?? "Unknown Code";
                AppendLog($"SUCCESS: Employee '{postedEmployeeCode}' posted correctly.");
                MessageBox.Show("Employee posted correctly!");
            }


            textBoxCode.Clear();
            textBoxName.Clear();
            textBoxAddress.Clear();
            textBoxCity.Clear();
            textBoxZipCode.Clear();
            textBoxTelephone.Clear();
        }
        else
        {
            if (string.IsNullOrWhiteSpace(aResult))
            {
                AppendLog("ERROR: The webservice failed and returned an empty response.");
                MessageBox.Show("Not posted! The webservice failed and returned an empty response.");
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(aResult);
                XmlNamespaceManager xmlNsManager = new XmlNamespaceManager(doc.NameTable);
                xmlNsManager.AddNamespace(doc.DocumentElement.Prefix, doc.DocumentElement.NamespaceURI);
                XmlNodeList errors = doc.SelectNodes("//maxs:Employees//maxs:Diagnostic//maxs:Errors//maxs:Error", xmlNsManager);
                string strMessage = string.Empty;

                if (errors != null)
                {
                    foreach (XmlNode node in errors)
                    {
                        strMessage += node.SelectSingleNode("maxs:Message", xmlNsManager)?.InnerText + "\n";
                    }
                }

                AppendLog($"FAILURE SPECIFIED: {strMessage.Replace("\n", " | ")}");
                MessageBox.Show(string.Format("Not posted, some error occurred!\n {0}", strMessage));
            }
        }
    }
    catch (Exception tbExc)
    {
        AppendLog($"EXCEPTION: {tbExc.GetType().Name} - {tbExc.Message}");
        MessageBox.Show(string.Format("Exception occurred: {0}", tbExc.Message));
    }
}

Disconnessione

Alla chiusura dell'applicazione è necessario disconnettere l'utente dal sistema invocando il metodo LogOff.

Di seguito il codice per eseguire la disconnessione:

private void LogoutCurrentUser()
{
    try
    {
        if (!string.IsNullOrEmpty(AppSession.AuthenticationToken))
        {
            using var client = new MicroareaLoginManagerSoapClient(
                                        MicroareaLoginManagerSoapClient.EndpointConfiguration.MicroareaLoginManagerSoap,
                                        $"{AppSession.BaseUrl.TrimEnd('/')}/LoginManager/LoginManager.asmx");
            client.LogOff(AppSession.AuthenticationToken);
        }
    }
    catch { }
}

 

Altre domande? Invia una richiesta

Commenti

Powered by Zendesk