• How to consume a web service, through client certification and Oauth2 Authentication, writing c# code.

    Versione Italiana.
    Who has done similar task , using visual studio, knows the IDE helps the developers, providing some classes useful to easly call a webservice. If the developer has available the WSDL file defining the service, Visual studio parses it , and automatically builds the libraries

    But, if the call must use a channel, encrypted by a client certificate, and further the server expect an Oauth2 authentication token , enclosed in the request, the task becomes quite harder

    With C# it’s quite simple to make an HTTP request using a client certificate to make the call, on the same HTTP request and also simple to add the OAuth2 token among the Headers.
    If the request is simple (It has few parameters and is not structured on several levels), the developer can send a raw HTTP request, inserting the parameters in the body of this.
    If instead the parameters of the request are many and very structured, doing such a thing would take a lot of time.

    I found a way to use the libraries generated by Visual studio, on an encrypted channel and with the Oauth2 authentication token.

    Below, is the code that would be used for a call with the usual method:

    var Binding = new BasicHttpBinding();
    EndpointAddress ServiceEndPoint = new EndpointAddress("http://EndpointAddress.com");
    ServiceReference.Serviceclient client = new ServiceReference.Serviceclient(Binding, ServiceEndPoint);
    ServiceReference.ServiceResult result = client.Method(ServiceParameter);

    If you want to make the call on an encrypted channel, you must first create a certificate object:

    X509Certificate2 certificate = new X509Certificate2("filePath.p12", "Password");

    Where the file containing the certificate must be in p12 format and the insertion of its relative password is mandatory.
    Next you need to create a binding type object different from the usual one, while the endpoint object will remain on the same type:

    var Binding = new WSHttpBinding();
    Binding.Security.Mode = SecurityMode.Transport;
    Binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    EndpointAddress ServiceEndPoint = new EndpointAddress(https://EndpointAddress.com);

    Note: This time the endpoint is on HTTPS, no longer on HTTP, indeed this type of binding is compatible only with https.

    Then you need to create the client object and set the certificate on it:

    ServiceReference.Serviceclient client = new ServiceReference.Serviceclient(Binding, ServiceEndPoint);
    ServiceReference.ServiceResult result = client.Method(ServiceParameter);
    
    Client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = 
    new System.ServiceModel.Security.X509ServiceCertificateAuthentication();
    System.ServiceModel.Security.X509CertificateInitiatorClientCredential certificateInitiator = 
    Client.ClientCredentials.ClientCertificate;
    certificateInitiator.Certificate = certificate;

    With this we have set up communication through the certified channel, now we must make sure that a token at our convenience is also included in the header of the generated HTTPS request. This is quite complicated, to be able to do it you need to act on the context of the call:

    using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
    {
           MessageHeader<string> header = new MessageHeader<string>("Bearer " + Oautoken);
           var untyped = header.GetUntypedHeader("Authorization", "");
           OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
           HttpRequestMessageProperty requestMessage = new 
           HttpRequestMessageProperty();
           requestMessage.Headers["Authorization"] = "Bearer " + "TokenString";          
           OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] 
           = requestMessage;
           result = client.method(serviceParameter);
    }


  • Come chiamare un Web service tramite certificato Client e autenticazione Oauth2 tramite libreria c#

    English version.
    Chi è già del mestiere , sa che Visual studio viene in aiuto degli sviluppatori che devono eseguire chiamata a servizi web, fornendo a questi, delle librerie generate analizzando il file WSDL del servizio.

    Ma quando la chiamata deve avvenire attraverso un canale cifrato, con un certificato client, ed in più il server si attende un token di autenticazione Oauth2 incluso nella richiesta, il lavoro si complica.

    Con C# è abbastanza semplice effettuare un richiesta HTTP utilizzando un certificato client per effettuare la chiamata, sulla stessa richiesta HTTP è semplice anche aggiungere il token OAuth2 fra gli Header.
    Se la richiesta è semplice (Ha pochi parametri e non strutturati su più livelli), lo sviluppatore può inviare una richiesta HTTP grezza, inserendo i parametri nel body di questa.
    Se invece i parametri della richiesta sono molti e molto strutturati , fare una cosa del genere, porterebbe via moltissimo tempo.

    Io ho trovato il modo di utilizzare le librerie generate da Visual studio , su un canale criptato e con il token di autenticazione Oauth2.

    Qui di seguito il codice che si userebbe per una chiamata con il metodo consueto:

    var Binding = new BasicHttpBinding();
    EndpointAddress ServiceEndPoint = new EndpointAddress("http://EndpointAddress.com");
    ServiceReference.Serviceclient client = new ServiceReference.Serviceclient(Binding, ServiceEndPoint);
    ServiceReference.ServiceResult result = client.Method(ServiceParameter);

    Volendo invece effettuare la chiamata su canale cifrato, occorre prima creare un oggetto certificate:

    X509Certificate2 certificate = new X509Certificate2("filePath.p12", "Password");

    Dove il file contenente il certificato deve essere in formato p12 e l’inserimento della sua relativa password è obbligatorio.
    Successivamente bisogna creare un oggetto di tipo binding diverso dal consueto, mentre l’oggetto endpoint rimarrà dello stesso tipo:

    var Binding = new WSHttpBinding();
    Binding.Security.Mode = SecurityMode.Transport;
    Binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    EndpointAddress ServiceEndPoint = new EndpointAddress(https://EndpointAddress.com);

    Nota bene: L’endpoint questa volta è su HTTPS , non più su HTTP, infatti questo tipo di binding è compatibile sono con https.

    Poi è necessario creare l’oggetto client e impostarvi sopra il certificato:

    ServiceReference.Serviceclient client = new ServiceReference.Serviceclient(Binding, ServiceEndPoint);
    ServiceReference.ServiceResult result = client.Method(ServiceParameter);
    
    Client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = 
    new System.ServiceModel.Security.X509ServiceCertificateAuthentication();
    System.ServiceModel.Security.X509CertificateInitiatorClientCredential certificateInitiator = 
    Client.ClientCredentials.ClientCertificate;
    certificateInitiator.Certificate = certificate;

    Con questo abbiamo impostato la comunicazione attraverso il canale certificato, adesso dobbiamo fare in modo che nell’header della richiesta HTTPS generata, venga incluso anche un token a nostro piacimento.
    Questo è abbastanza complicato, per poterlo fare bisogna agire sul contesto della chiamata:

    using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
    {
           MessageHeader<string> header = new MessageHeader<string>("Bearer " + Oautoken);
           var untyped = header.GetUntypedHeader("Authorization", "");
           OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
           HttpRequestMessageProperty requestMessage = new 
           HttpRequestMessageProperty();
           requestMessage.Headers["Authorization"] = "Bearer " + "TokenString";          
           OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] 
           = requestMessage;
           result = client.method(serviceParameter);
    }


  • I cavalli più veloci

    Un tizio è proprietario di 25 cavalli, e vuole riuscire a capire quali di questi sono i 3 più veloci.
    Per fare questo può fare gareggiare in velocità i cavalli, facendo gareggiare al massimo 5 cavalli per ogni gara. Non può usare cronometri.

    Qual’è il minor numero di gare necessario per determinare i 3 cavalli più veloci?


  • Pirati e Lucchetti

    Cinque pirati decidono di mettere il frutto delle loro scorribande in un forziere che possa essere aperto solo quando sono presenti tre di loro, chiunque essi siano. Per fare ciò hanno escogitato un sistema alquanto ingegnoso, che ha richiesto lunghi ragionamenti. “Se fossimo soltanto io e te – Dice un pirata al suo vicino – sarebbe semplice. Basterebbe chiudere il forziere con due lucchetti; Io avrei una chiave e tu l’altra e solamente insieme potremmo aprire il forziere”. “Anche con tre soli pirati sarebbe semplice: tre lucchetti, ciascuno munito di due chiavi; e ciascun pirata con due chiavi diverse. In questo modo è sempre necessaria la presenza di due pirati per aprire il forziere”. “Ma noi siamo in cinque, è un po’ più complicato!” Comunque alla fine il forziere viene chiuso con più lucchetti e a ciascun pirata viene assegnato lo stesso numero di chiavi. Naturalmente ogni chiave può aprire un solo lucchetto, ma ad ogni lucchetto corrispondono più chiavi che finiscono in mano a pirati diversi. Come avevano stabilito, il forziere non potrà mai essere aperto senza la presenza di tre di loro.

    Di quanti lucchetti avranno bisogno come minimo i cinque pirati?

    Da “La settimana enigmistica”




  • My degree Thesis

    After much thought, I decided to give this important scientific document to the world 😀

    It is available by clicking on the button below.

    My thesis is about Computer Vision. It aims to implement a system capable of providing augmented reality in an industrial environment.

    The accuracy of an application based on augmented reality and the capabilities of the tracking system used. In practice, the system that determines the position of the point of view with respect to the environment.

    During this study, two tracking systems were examined and compared.

    The first uses the Vuforia platform, a technology capable of tracking in restricted areas, with the use of fiducial markers. It composes a structure of markers (the Markerfield) and allows its use in a larger space.

    The second is a hybrid system. It uses a Marker as a starting point and autonomously extends the traceable area, making use of reference points naturally present in the environment.

    Not going into details, these are all in the document I prepared.

    Enjoy the reading.

    Let me know if you have any criticisms, ideas, possible applications, etc.


  • La mia tesi di Laurea

    Dopo averci pensato molto, ho deciso di donare al mondo questo documento scientifico cosi importante 😀

    Esso è disponibile cliccando sul bottone sottostante.

    La mia tesi di laurea è in ambito Computer Vision. Essa si propone allo scopo di implementare un sistema capace di fornire realtà aumentata in ambito industriale.

    La precisione di un’applicazione basata sulla realtà aumentata e data delle capacità del sistema di tracciamento utilizzato. In pratica il sistema che determina la posizione del punto di vista rispetto all’ambiente.

    Durante questo studio sono stati presi in esame e confrontati due sistemi di tracciamento.

    Il primo fa uso della piattaforma Vuforia, tecnologia capace di effettuare il tracciamento in aree ristrette , con l’uso di marker fiduciali. Compone una struttura di markers (il Markerfield) e ne consente l’uso in uno spazio più ampio.

    Il secondo è un sistema ibrido. Fa uso di un Marker come punto di partenza ed estende autonomamente l’area tracciabile, facendo uso di punti di riferimento naturalmente presenti nell’ambiente.

    Non scendo nei dettagli, questi sono tutti nel documento che ho preparato.

    Buona lettura.

    Fatemi sapere se avete in proposito , critiche, idee , possibili applicazioni , etc.


  • Like operator in x++

    Sometimes we have to search some records in a table having a field that satisfies a regular expression. For  istance, if i want to retrieve all Customer having the name starting by “A” i should fetch al Record of CustTable, having the Name field that match with the expression “A*”.

    To perform this kind of research we can use the operator like that we can insert both in query and in rest of the code. But there is an important issue. The behaviour of this operator used in queries is different from the behavior of the same operator used out of a query.

    into queries:

    • “ABC123” like “ABC*” return false value.
    • “ABC123” like “ABC%” return true value.

    Out of queries:

    • “ABC123” like “ABC*” return true value.
    • “ABC123” like “ABC%” return false value.

    Namely, the characters “*” and “%” exchange their semantics.

    The ax user is used to insert “*” in the form to filter the record or insert any kind of query on user side. Then the developer has to “Translate” the regulare expression replacing the “*” character with “%” character and perform the query :

    CustTable custTable;
    str valueInsertedByUser = "ABC*";
    select custTable where CustTable.Name like strReplace(valueInsertedByUser,"*","%");
    return custTable;
    
    

    The task becomes more complicated when the the regular expression is in a table field, and we have to retrieve a record having a regular expression (written by the user, with “*”) that match a particular string value. For example : I have three record in a table:

    A*
    B*
    C*

    I Have to search the record matching  to the string B34545644, that’s the second.

    In that case , since i cannot perform a string replacement directly on the DBServer i have to fetch all records and use the like operator as out of a query:

    Example table table;
    str searchingValue = "B34545644";
    while select table
    {
        if(searchingValue like table.field) return table;
    }

    Since Like operator in this case is used out of a query, it works through “*” and no replacement is needed.


  • How to choose PackingSlipId for CustPackingSlip by code in AX 365

    The standard AX procedure allows to manually choose the packingslipId just for VendPackingSlipJour.  To choose the packingSlipId for CustPackingSlipJour in AX 365 is not a trivial task, because developers cannot perform overlayering to change the system behaviour.

    Class SalesFormLetter , LetterFormCreate and their subclasses, used by the system to create the custpackingslip,  are very “armored”. I’ve not found any useful hookable method in these classes.

    Reading the code into the classes , i noticed the procedure first gets the sequence number for the packingSlipId , later on it initializes the custpackingslipjour tablebuffer, using the field in relative SalesTable record.

    Then i decided to add a new field in SalesTable Table called “ChoosenPackingSlipId” and to resolve the task using an event handler ad the end of initialization method of CustPackingslipJour. It is the following:

     [PostHandlerFor(tableStr(CustPackingSlipJour),tableMethodStr(CustPackingSlipJour, initFromSalesTable))]
     public static void CustPackingSlipJour_Post_initFromSalesTable(XppPrePostArgs args)
     {
        SalesTable salestable = Args.getArg("_salesTable");
        CustPackingSlipJour CustpackSlipjour = args.getthis();
        CustPackingSlipJour existentCustpackSlipjour;
        select firstonly existentCustpackSlipjour where existentCustpackSlipjour.PackingSlipId == salestable.ChoosenPackingSlipId;
        if(!existentCustpackSlipjour)
        {
           CustpackSlipjour.PackingSlipId= salestable.ChoosenPackingSlipId;
        }
     }
    
    

    So that, when the procedure to create CustPackingSlip is called by code or a user create a Custpackingslip by user side, as result the file custpackingslipId is equal to the field “ChoosenPackingslipId”


  • Post CustPackingSlip in x++ on Dynamics AX 365

    Searching a way to post a CustPackingSlip referred to a sales order by code in AX, i have found a lot of posts that explain how to resolve this task through the following code :

    SalesFormLetter salesFormLetter;
    SalesTable salesTable;
    salesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip);
    salesFormLetter.update(salesTable, systemDateGet(), SalesUpdate::PackingSlip, AccountOrder::None, NoYes::No, NoYes::No, NoYes::No);

    Unfortunately this code seems to be written only for AX 2012 or older version of Ax, because on AX7 it does not work fine.

    Then i’ve found a code written by Muhammad Anas Khan, made to post the VendPackingslips. Following the same staps i’ve write my version to post the CustPackingSlip.

    public static void PostPackingSlip(salesTable _salesTable)
    {
            SalesLine                       salesLine;
            SalesFormLetter salesformletter;
            SalesFormletterParmData salesformletterparmData;
            SalesParmUpdate salesParmUpdate;
            SalesParmTable salesParmTable;
            SalesParmLine salesParmLine;
            salesformletterparmData = SalesFormletterParmData::newData(DocumentStatus::PackingSlip,VersioningUpdateType::Initial);
            salesformletterparmData.parmOnlyCreateParmUpdate(true);
            salesformletterparmData.createData(false);
            salesParmUpdate = salesformletterparmData.parmParmUpdate();
            salesParmTable.clear();
            salesParmTable.initFromSalesTable(_salesTable);
            salesParmTable.TransDate             = DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());
            salesParmTable.Ordering              = DocumentStatus::PackingSlip;
            salesParmTable.ParmJobStatus         = ParmJobStatus::Waiting;
            salesParmTable.ParmId                = salesParmUpdate.ParmId;
            salesParmTable.insert();
    
            while  select  salesLine
            where salesLine.SalesId == _salesTable.SalesId
            {
                salesParmLine.clear();
                salesParmLine.initFromSalesLine(salesLine);
                SalesParmLine.ParmId = salesParmTable.ParmId;
                SalesParmLine.TableRefId = SalesParmTable.TableRefId;
                //I want to deliver all ordered quantity
                SalesParmLine.DeliverNow = salesline.SalesQty;
                SalesParmLine.modifiedDeliverNow();
                SalesParmLine.setQty(DocumentStatus::PackingSlip, false);
                SalesParmLine.setLineAmount();
                SalesParmLine.insert();
            }
            SalesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip);
            SalesFormLetter.parmVersioningUpdateType(VersioningUpdateType::Initial);
            SalesFormLetter.salesParmUpdate(SalesformletterParmData.parmParmUpdate());
            SalesFormLetter.parmCallerTable(_salesTable);
            SalesFormLetter.parmId(salesParmTable.ParmId);
            SalesFormLetter.specQty(SalesUpdate::DeliverNow);
            SalesFormLetter.transDate(DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone()));
            SalesFormLetter.proforma(false);
     SalesFormLetter.run();
        }

  • Diventa anche tu un tester!!

    Hai mai sognato di essere una di quelle persone che vedi su Youtube fare le recensioni sui nuovi prodotti, e magari di poter ricevere gratuitamente tutti questi prodotti?

    Adesso lo puoi fare, ti basta seguire questo Link.

    Per poter effettuare questi test ti è sufficiente avere un account Amazon, che ti serve per poter acquistare gli oggetti che ti vengono proposti, e un account Paypal , che serve ai gestori di questo servizio per farti avere il denaro necessario a comprare i prodotti attraverso Amazon.

    Quello che ti viene richiesto è di fornire una recensione su Amazon per ogni prodotto che ti è stato “fornito” in questo modo. Non è necessario che tu registri una recensione come un tester professionista su Youtube, è sufficiente la sola recensione su Amazon.

    Il numero di oggetti che potrai richiedere contemporaneamente , salirà con il numero di Task completati. Per Task si intende tutta la serie di operazioni necessarie per ogni singolo prodotto: Richiesta sul sito, Ordine su Amazon, Ricezione del pacco, Testing e scrittura della recensione.

    Ricordati di iscriverti direttamente utilizzando il link che ti ho fornito io. E’ mio personale ed io ho già completato con successo molti task. Quindi iscrivendoti con quel link, farai sapere ai gestori del sito che sei amico mio (ovvero una persona affidabile) e potrai avere fin da subito molti prodotti disponibili. Di norma i primi task disponibili cominciano ad apparire il giorno successivo all’iscrizione.

    Sempre perché ti invito come amico, e quindi per te ci metto la faccia, vedi di comportarti bene e di completare i task una volta che li hai  iniziati. Quelli che si fanno dare i soldi per acquistare i prodotti, e poi scappano senza comprarli, non sono ben visti dai gestori del sito…

    Il sito è in inglese, ma alla portata di tutti. Comunque per ogni informazione riguardo al funzionamento non esitare a scrivermi.

    Buon divertimento!! 😀