Wajahat Wasti, Author at Impulz Technologies LLC https://impulztech.com/author/wajahat-wasti/ Microsoft Dynamics and Power Platform consulting company Wed, 06 Dec 2023 14:27:24 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.3 https://impulztech.com/wp-content/uploads/2022/08/cropped-impulz-tech-32x32.png Wajahat Wasti, Author at Impulz Technologies LLC https://impulztech.com/author/wajahat-wasti/ 32 32 Fix Database Synchronization Errors in Microsoft Dynamics AX 2012 https://impulztech.com/database-synchronization-errors-in-microsoft-dynamics-ax-2012/ Wed, 06 Dec 2023 14:27:24 +0000 https://impulztech.com/?p=3559 In this blog i will cover how to remove Database Synchronization Errors in Microsoft Dynamics AX 2012.This blog post takes you through the steps you need to take and shares a SQL script sample to make it work. Sample Error Cannot execute data definition language command on (). The SQL database has issued an error. […]

The post Fix Database Synchronization Errors in Microsoft Dynamics AX 2012 appeared first on Impulz Technologies LLC.

]]>

In this blog i will cover how to remove Database Synchronization Errors in Microsoft Dynamics AX 2012.This blog post takes you through the steps you need to take and shares a SQL script sample to make it work.

Sample Error

Cannot execute data definition language command on (). The SQL database has issued an error.

SQL Statement: ‘SP_RENAME’ ………

Field1 is already in use as Column name and would cause a duplicate that is not permitted.

Reason

The errors are due to KBs installation on different occasions. There are issue in some KB related fields where the Element id seems mismatched. They must match in SQL and AX2012 . In the database exists an older copy of the table with different Element IDs, which are not in sync with the Element IDs present in AX2012. Therefore, during database synchronization, SQL Server presents an error because of the ID mismatch.

Solution

To resolve database synchronization errors in Microsoft Dynamics AX 2012, first take data backup for tables from SQL Server Management Studio by generate script so that after changes in table we can import again. Next we need to Drop the table from SQL. Now go to AX2012 and synchronize the table by right clicking on table. Once sync is completed, check the table created in SQL. Next is to import the data back in the table by running the script.

Steps to fix errors

1-Go to SQL Management studio and generate data script to take data backup

2-Drop table from SQL (If unable to delete table due to referenced tables then rename the fields which have issues)

Drop table VENDPARAMETERS

3-Synchronize the table from AX2012 AOT

4-Check Table in SQL and import data using script we generated previously

Note: Same doing this we can also fix Issues in Views.

Once you are done with all the sync errors for tables and views Run the Full Sync from AX Environment.

Note: This approach is not recommended for production environment directly it must be tested first on development environment.

Thanks

The post Fix Database Synchronization Errors in Microsoft Dynamics AX 2012 appeared first on Impulz Technologies LLC.

]]>
Dynamics 365 Finance and Supply Chain: Access development environment https://impulztech.com/dynamics-365-finance-and-supply-chain-access-development-environment/ Wed, 18 Oct 2023 13:35:12 +0000 https://impulztech.com/?p=3156 Microsoft has changed how the admin user is setup in Dynamics 365 Finance and Supply Chain development virtual machine in order to access the Dynamics 365 development environment after the release of the VHD for version 10.0.24 in LCS. Prior to this version, user just needed to provide a valid domain email in Admin User […]

The post Dynamics 365 Finance and Supply Chain: Access development environment appeared first on Impulz Technologies LLC.

]]>

Microsoft has changed how the admin user is setup in Dynamics 365 Finance and Supply Chain development virtual machine in order to access the Dynamics 365 development environment after the release of the VHD for version 10.0.24 in LCS. Prior to this version, user just needed to provide a valid domain email in Admin User Provisioning tool to access the Dynamics 365 development environment. But now, when you instantly try to execute the Admin User Provisioning Tool with the domain user, it will give the following error.

Now you need to run a script that will create self-signed certificates to be used on the virtual machine, and a customer-provided application registration ID for authentication. After successfully running the script, the environment will be ready for use.

Reason to introduce App registration

App Registrations enable custom-built or third-party applications to use Microsoft Entra ID security features. By using these features, organizations can ensure that their applications and resources are accessed securely and only by authorized users.

App Registrations can be used to grant permissions to users and groups, configure SSO, and define custom API permissions that the application can request. They also enable administrators to monitor and audit application usage, view application-specific logs, and set up alerts and notifications for suspicious activity.

By using previous approach if we run the AdminUserProvisioning tool we will encounter above error while configure VHD setup for D365 FO 10.0.24 version or later.

Steps to set up for new 10.0.24 version or later

There are some steps required before you can assign it to your Domain:

1. Go tohttps://portal.azure.com > Microsoft Entra ID > App Registration and register a new App

Note: Microsoft has renamed Azure Active Directory (Azure AD) to Microsoft Entra ID for the following reasons:

    • to communicate the multicloud, multiplatform functionality of the products,
    • to alleviate confusion with Windows Server Active Directory, and
    • to unify the Microsoft Entra product family.
    • Register a new application in Microsoft Entra ID

2. Provide the One-Box URL as reponse address eg: https://usnconeboxax1aos.cloud.onebox.dynamics.com/

3. Copy the AppID to your clipboard will use later

4. App Registration for Dynamics 365 FO 10.0.24 One-Box Environment completed.

5. Execute the “Generate Self-Signed Certificates” PowerShell script from the Desktop

6. Provide the AppID copied from the App Registration

7. Execute the Admin Provisioning Tool and provide your Domain account address

8. Open https://usnconeboxax1aos.cloud.onebox.dynamics.com/ in Edge and login

Thanks.

 

The post Dynamics 365 Finance and Supply Chain: Access development environment appeared first on Impulz Technologies LLC.

]]>
Microsoft Dynamics 365 Finance and Operations: Importing deployable package to UAT/Production using Lifecycle Services https://impulztech.com/microsoft-dynamics-365-finance-and-operations-importing-deployable-package-to-uat-production-using-lifecycle-services/ Mon, 10 Apr 2023 08:26:21 +0000 https://impulztech.com/?p=3086 Overview In Microsoft Dynamics 365 Finance and Operations, development and customization can be done within development environment and deployed to UAT / Production environment. In this blog we are going to discuss how these changes can be deployed to UAT / Production environment Steps for deploying changes using Lifecycle Services Step -1: Create Deployable package […]

The post Microsoft Dynamics 365 Finance and Operations: Importing deployable package to UAT/Production using Lifecycle Services appeared first on Impulz Technologies LLC.

]]>

Overview

In Microsoft Dynamics 365 Finance and Operations, development and customization can be done within development environment and deployed to UAT / Production environment. In this blog we are going to discuss how these changes can be deployed to UAT / Production environment

Steps for deploying changes using Lifecycle Services

Step -1: Create Deployable package and save it in a folder.

Step -2: Go to https://lcs.dynamics.com and enter your credentials

Step-3: Click on your implementation project. Then go to Asset Library using 3 bars icon as shown in the below screenshot.

Step-4: Go to Software deployable package Tab in Asset Library. Then add the new package here which we have created from dev environment.

What is a deployable package?

Let’s first define what a development environment package or a deployable package is, before we dive into the deployment process. A deployable package is a collection of customizations and extensions that have been developed in a development environment. This package contains the code, metadata, and configurations that can then deploy to the UAT or Production environment.

Step-5: As we can see in below screenshot, we need to give name for uploading our package into Asset Library first. Then the package will be eligible to deploy to UAT or Production.

Step-6: Once package is added into asset library and if you want to publish it in the UAT environment, click on the highlighted option in the screenshot below.

Step-7: Now go to navbar Maintain and click on Apply updates

Step-8: Provide unique name for you Package. Such as write package name with date and then select the package uploaded in asset library and click on Apply 

Step-9: It can take about 1 to 3 or more hours depending on the size of the package.

Step 10: After successful deployment we can check the Activity status completed or Rollback. If we get any errors during the deployment, it will be rollback and we need to fix it in development environment. Afterwards the whole process of deployment will repeat.

Best Practices for Deploying a Development Environment Package to UAT/Production

To ensure a successful deployment, it’s important to follow these best practices:

    1. Always test the deployment in a non-production environment first.
    2. Include all the required models and packages in the deployable package.
    3. Properly configure the target environment so that it can meet the requirements of the customizations and extensions.
    4. Take a backup of the target environment before deploying the package.
    5. Monitor the deployment progress and resolve any issues that arise during the deployment process.

Good luck.

 

The post Microsoft Dynamics 365 Finance and Operations: Importing deployable package to UAT/Production using Lifecycle Services appeared first on Impulz Technologies LLC.

]]>
Dynamics 365 Finance and Operations: Acquire access token using OAuth 2.0 https://impulztech.com/dynamics-365-finance-and-operations-acquire-access-token-using-oauth-2-0/ Tue, 20 Sep 2022 15:57:04 +0000 https://impulztech.com/?p=2691 This blog discusses how to obtain access token in Dynamics 365 Finance and Operations to enable data access of another application via APIs that use OAuth 2.0 authorization protocol. First of all lets see the definitions of some of the terms we are going to use here: Access token Use of access token in API […]

The post Dynamics 365 Finance and Operations: Acquire access token using OAuth 2.0 appeared first on Impulz Technologies LLC.

]]>

This blog discusses how to obtain access token in Dynamics 365 Finance and Operations to enable data access of another application via APIs that use OAuth 2.0 authorization protocol. First of all lets see the definitions of some of the terms we are going to use here:

  • Access token
  • Use of access token in API
  • OAuth2.0 authentication in web API

Access token
Access tokens are used in token-based authentication to allow an application to access an API. The application receives an access token after a user successfully authenticates and authorizes access, then passes the access token as a credential when it calls the target API. The passed token informs the API that the bearer of the token has been authorized to access the API and perform specific actions specified by the scope that was granted during authorization.

Use of access token in API
API tokens allow a user to authenticate with cloud apps and bypass two-step verification and single sign-on, and retrieve data from the instance through REST APIs. Token controls allow admins to view and revoke the use of API tokens by their managed accounts. (In this article we are discussing particularly OAuth2.0 Code Grant Authorization to enable our application to obtain Access Token).

OAuth 2.0 authentication in Web API
OAuth2 is the preferred method of authenticating access to the API. OAuth2 allows authorization without the external application getting the user’s email address or password. Instead, the external application gets a token that authorizes access to the user’s account.

To acquire the access token in Dynamics 365 Finance and Operations, there are two steps; first is to generate the authorization code and second is to use the authorization code to request for the token.

(1)  Generate Authorization code
The authorization code is a temporary code that the client will exchange for an access token. The code itself is obtained from the authorization server where the user gets a chance to see what the information the client is requesting, and approve or deny the request.

The authorization code flow offers a few benefits over the other grant types. When the user authorizes the application, they are redirected back to the application with a temporary code in the URL. The application exchanges that code for the access token. When the application makes the request for the access token, that request can be authenticated with the client secret, which reduces the risk of an attacker intercepting the authorization code and using it themselves. This also means the access token is never visible to the user or their browser, so it is the most secure way to pass the token back to the application, reducing the risk of the token leaking to someone else.

Below code is to request the authorization code by sending the authURL and client Id provided by the application that needs to be integrated with D365 FnO. Use browser.navigate which navigates/loads the info at the specified URL into a new browser window.

public void generateAuthCode()
{
Browser browser;
str     authURL =  "https://console-sandbox.foodics.com/authorize?response_type=code&client_id=%1&redirect_uri=%2";
str     clientId = "123456789123456789123546789123456";
str     callbackURL = "https://usnconeboxax1aos.cloud.onebox.dynamics.com";

browser = new Browser();

str url = strFmt(authURL, clientId, callbackURL);
browser.navigate(url);
}

The authorization URL is usually in a format such as:

‘https://console-sandbox.abc.com/authorize?response_type=code&client_id=123456-78910-111213-aaa0b60d5c0a&redirect_uri=https://usnconeboxax1aos.cloud.onebox.dynamics.com/’

Note: You will most likely first need to register your redirect URL at the service before it will be accepted. This also means you can’t change your redirect URL per request. Instead, you can use the state parameter to customize the request. See below for more information.

Once the authorization code is returned in the browser window, it will be used to get the access token.

(2)  Generate access token using authorization code
Following parameters are required in the body of our request.

  • grant_type: this is to identify the grant type as OAuth 2.0 supports multiple grant types. Here we are using authorization_code: as grant_type.
  • code: the authorization code your app obtained upon user authorization by using above step.
  • client_id: your app client id, given to you by the other application.
  • client_secret: your app secret, given to you by the other application.
  • redirect_uri: must be the same redirect URI you redirected the user to during user authorization.

Following is the code to acquire access token.

First create a data contract class to hold the parameters required for token generation.

[DataContract]
public class GenerateAccessTokenDataContract
{
    [DataMember("grant_type")]
    public str paramGrantType(str _grantType = grantType)
    {
        grantType = _grantType;
        return grantType;
    }

    [DataMember("code")]
    public Str1260 paramAuthCode(Str1260 _authCode = authCode)
    {
        authCode = _authCode;
        return authCode;
    }

    [DataMember("client_id")]
    public str paramClientId(str _clientId = clientId)
    {
        clientId = _clientId;
        return clientId;
    }

    [DataMember("client_secret")]
    public str paramClientSecret(str _clientSecret = clientSecret)
    {
        clientSecret = _clientSecret;
        return clientSecret;
    }

    [DataMember("redirect_uri")]
    public str paramRedierectUri(str _redierectUri = redierectUri)
    {
        redierectUri = _redierectUri;
        return redierectUri;
    }

    [DataMember("access_token")]
    public Str1260 paramAccessToken(Str1260 _accessToken = accessToken)
    {
        accessToken = _accessToken;
        return accessToken;
    }
}

Create a new class named GenerateAccessToken and write following code:

public class GenerateAccessToken extends Runbase
{
    str authorizationCode;
    str jsonString;

    public static void main(Args _args)
    {
           GenerateAccessToken generateAccessToken;
           generateAccessToken = new GenerateAccessToken();
           if (generateAccessToken.prompt())
           generateAccessToken.runOperation();
    }

    public void run()
    {
         ttsbegin;
         this.setAccessToken();
         ttscommit;
    }

    public void setAccessToken()
    {
        Newtonsoft.Json.Linq.JObject    jObject;
        str    resultString;
        str   clientId = "123456789123456789123546789123456";
        str   secretKey = "abc1234def5678";
        str   callbackURL = "https://usnconeboxax1aos.cloud.onebox.dynamics.com";
        str   accessTokenURL = "https://api-sandbox.abc.com/oauth/token";

        GenerateAccessTokenDataContract generateAccessTokenDataContract = new GenerateAccessTokenDataContract ();
        Microsoft.Dynamics.Client.ServerForm.Contexts.SessionContext sessionContext;
        System.Uri currentUrl = null;
        sessionContext = Microsoft.Dynamics.Client.ServerForm.Contexts.SessionContext::get_Current();

        if (sessionContext)
        {
            currentUrl = sessionContext.get_RequestUrl();
        }

        Str1260 authUrl = currentUrl.ToString();
        GenerateAccessToken::splitAuthCode(authUrl);

        generateAccessTokenDataContract.paramGrantType("authorization_code");
        generateAccessTokenDataContract.paramAuthCode(authenticationCode);
        generateAccessTokenDataContract.paramClientId(clientId);
        generateAccessTokenDataContract.paramClientSecret(secretKey);
        generateAccessTokenDataContract.paramRedierectUri(callbackURL);

        jsonString = this.serializeAccessTokenJson(generateAccessTokenDataContract);

        jObject = Newtonsoft.Json.Linq.JObject::Parse(jsonString);
        jObject.Property("access_token").Remove();

        resultString = this.callApi(jsonString, accessTokenURL, accessTokenURL, "Post");
        generateAccessTokenDataContract = this.deserializeCustJson(resultString);
        str token = fdsAcessTokenDataContract.paramAccessToken();

        info(token);
    }

    static void splitAuthCode(Str1260 _authUrl)
    {
        List strlist=new List(Types::String);
        ListIterator iterator;
        str _Value;
        int counter = 0;

        strlist=strSplit(_authUrl,"=");
        iterator = new ListIterator(strlist);
        while(iterator.more())
        {
            counter++;
            _Value =iterator.value();
            if(counter == 2)
            {
                authorizationCode = strReplace(_Value, "&cmp", "");
            }
            iterator.next();
        }
    }

    public str serializeAccessTokenJson(GenerateAccessTokenDataContract _datContract)
    {
        jsonstring = FormJsonSerializer::serializeClass(_datContract);
        return jsonstring;
    }

    public GenerateAccessTokenDataContract deserializeCustJson(str _jsonstring)
    {
        GenerateAccessTokenDataContract generateAccessTokenDataContract = FormJsonSerializer::deserializeObject(classNum(GenerateAccessTokenDataContract),_jsonstring);
        return generateAccessTokenDataContract;
    }

    public  str callApi(str _jsonString, str _url, str, _accessTokenURL, str _urlType)
    {
        RetailCommonWebAPI  webApi = RetailCommonWebAPI::construct();
        System.IO.StringWriter          stringWriter;
        Newtonsoft.Json.JsonTextWriter  jsonWriter;
        System.Net.HttpWebRequest       request;
        System.Net.HttpWebResponse      response;
        System.IO.StreamWriter          streamWrite;
        System.Net.ServicePoint         servicePoint;
        CLRObject                       clrObj;
        System.Text.Encoding            utf8;
        System.Exception                ex;
        System.Byte[]                   byteArraynew;
        System.Net.WebHeaderCollection  headers = new System.Net.WebHeaderCollection();
        str                             msgStatusCode;
        str                             jsonmsg;
        str                             access_token;

        try
        {
            new InteropPermission(InteropKind::ClrInterop).assert();
            str  byteStr = strfmt('%1:%2', "USERNAME", "PASSWORD");
            clrObj = System.Net.WebRequest::Create(_url);
            request  = clrObj;
            request.set_Method(_urlType);
            request.set_KeepAlive(true);
            utf8  = System.Text.Encoding::get_UTF8();
            byteArraynew  = utf8.GetBytes(byteStr);
            byteStr = System.Convert::ToBase64String(byteArraynew);
            headers.Add('Authorization', strFmt(" Bearer %1", access_token));
            request.set_Headers(headers);
            request.set_Accept("application/json");
            request.set_ContentType("application/json");
            servicePoint = request.get_ServicePoint();
            servicePoint.set_Expect100Continue(false);

            stringWriter = new System.IO.StringWriter();
            jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter);
            streamWrite = new System.IO.StreamWriter(request.GetRequestStream());
            streamWrite.Write(_jsonString);
            streamWrite.Flush();
            streamWrite.Close();
            response = request.GetResponse();
            System.IO.StreamReader streamRead = new System.IO.StreamReader(response.GetResponseStream());  
            jsonmsg = streamRead.ReadToEnd().ToString();

            msgStatusCode = response.StatusCode.ToString();
        }

        catch  (Exception::CLRError)
        {
            ex = CLRInterop::getLastException().getbaseexception();
            error(ex.get_message());
        }       
        return jsonmsg;
    }
}

Note: Access token URL will be provided by the application than needs to be integrated with Dynamics 365 Finance and Operations. If your request to get access token is valid, the authorization server will return an access token otherwise it will return an error message.

The post Dynamics 365 Finance and Operations: Acquire access token using OAuth 2.0 appeared first on Impulz Technologies LLC.

]]>