Categories: Tutorials

Working with NAV and Azure App Service

11 min read

In this article by Stefano Demiliani, the author of the book Building ERP Solutions with Microsoft Dynamics NAV, we will experience the quick solution to solve complex technical architectural scenarios and create external applications within a blink of an eye using Microsoft Dynamics NAV.

(For more resources related to this topic, see here.)

The business scenario

Imagine a requirement where many Microsoft Dynamics NAV instances (physically located at different places around the world) have to interact with an external application. A typical scenario could be a headquarter of a big enterprise company that has a business application (called HQAPP) that must collect data about item shipments from the ERP of the subsidiary companies around the world (Microsoft Dynamics NAV):

The cloud could help us to efficiently handle this scenario. Why not place the interface layer in the Azure Cloud and use the scalability features that Azure could offer? Azure App Service could be the solution to this.

We can implement an architecture like the following schema:

Here, the interface layer is placed on Azure App Service. Every NAV instance has the business logic (in our scenario, a query to retrieve the desired data) exposed as an NAV Web Service. The NAV instance can have an Azure VPN in place for security.

HQAPP performs a request to the interface layer in Azure App Service with the correct parameters. The cloud service then redirects the request to the correct NAV instance and retrieves the data, which in turn is forwarded to HQAPP. Azure App Service can be scaled (manually or automatically) based on the resources requested to perform the data retrieval process.

Azure App Service overview

Azure App Service is a PaaS service for building scalable web and mobile apps and enabling interaction with on-premises or on-cloud data. With Azure App Service, you can deploy your application to the cloud and you can quickly scale your application to handle high traffic loads and manage traffic and application availability without interacting with the underlying infrastructure. This is the main difference with Azure VM, where you can run a web application on the cloud but in a IaaS environment (you control the infrastructure like OS, configuration, installed services, and so on).

Some key features of Azure App Service are as follows:

  • Support for many languages and frameworks
  • Global scale with high availability (scaling up and out manually or automatically)
  • Security
  • Visual Studio integration for creating, deploying and debugging applications
  • Application templates and connectors available

Azure App Service offers different types of resources for running a workload, which are as follows:

  • Web Apps: This hosts websites and web applications
  • Mobile Apps: This hosts mobile app backends
  • API Apps: This hosts RESTful APIs
  • Logic Apps: This automates business processes across the cloud

Azure App Service has the following different service plans where you can scale from depending on your requirements in terms of resources:

  • Free: This is ideal for testing and development, no custom domains or SSL are required, you can deploy up to 10 applications.
  • Shared: This has a fixed per-hour charge. This is ideal for testing and development, supports for custom domains and SSL, you can deploy up to 100 applications.
  • Basic: This has a per-hour charge based on the number of instances. It runs on a dedicated instance. This is ideal for low traffic requirements, you can deploy an unlimited number of apps. It supports only a single SSL certificate per plan (not ideal if you need to connect to an Azure VPN or use deployment slots).
  • Standard: This has a per-hour charge based on the number of instances. This provides full SSL support. This provides up to 10 instances with auto-scaling, automated backups, up to five deployment slots, ideal for production environments.
  • Premium: This has per-hour charge based on the number of instances. This provides up to 50 instances with auto-scaling, up to 20 deployment slots, different daily backups, dedicated App Service Environment. Ideal for enterprise scale and integration.

Regarding the application deployment, Azure App Service supports the concept of Deployment Slot (only on the Standard and Premium tiers). Deployment Slot is a feature that permits you to have a separate instance of an application that runs on the same VM but is isolated from the other deployment slots and production slots active in the App Service.

Always remember that all Deployment Slots share the same VM instance and the same server resources.

Developing the solution

Our solution is essentially composed of two parts:

  • The NAV business logic
  • The interface layer (cloud service)

The following steps will help you retrieve the required data from an external application:

  1. In the NAV instances of the subsidiary companies, we need to retrieve the sales shipment’s data for every item. To do so, we need to create a Query object that reads Sales Shipment Header and Sales Shipment Line and exposes them as web services (OData).The Query object will be designed as follows:

  2. For every Sales Shipment Header web service, we retrieve the corresponding Sales Shipment Lines web service that have Type as DataItem:

    I’ve changed the name of the field No. in Sales Shipment Line in DataItem as ItemNo because the default name was in used in Sales Shipment Header in DataItem.

  3. Compile and save the Query object (here, I’ve used Object ID as 50009 and Service Name as Item Shipments).
  4. Now, we will publish the Query object as web service in NAV, so open the Web Services page and create the following entries:
    • Object Type: Query
    • Object ID: 50009
    • Service Name: Item Shipments
    • Published: TRUE
  5. When published, NAV returns the OData service URL.
  6. This Query object must be published as web service on every NAV instances in the subsidiary companies.
  7. To develop our interface layer, we need first to download and install (if not present) the Azure SDK for Visual Studio from https://azure.microsoft.com/en-us/downloads/.
  8. After that, we can create a new Azure Cloud Service project by opening Visual Studio and navigate to File | New | Project, select the Cloud templates, and choose Azure Cloud Service.
  9. Select the project’s name (here, it is NAVAzureCloudService) and click on OK.
  10. After clicking on OK, Visual Studio asks you to select a service type. Select WCF Service Web Role, as shown in the following screenshot:

  11. Visual Studio now creates a template for our solution. Now right-click on the NAVAzureCloudService project and select New Web Role Project, and in the Add New .NET Framework Role Project window, select WCF Service Web Role and give it a proper name (here, we have named it WCFServiceWebRoleNAV):

  12. Then, rename Service1.svc with a better name (here, it is NAVService.svc).
  13. Our WCF Service Web Role must have the reference to all the NAV web service URLs for the various NAV instances in our scenario and (if we want to use impersonation) the credentials to access the relative NAV instance. You can right-click the WCFServiceWebRoleNAV project, select Properties and then the Settings tab. Here you can add the URL for the various NAV instances and the relative web service credentials.

Let’s start writing our service code.

We create a class called SalesShipment that defines our data model as follows:

public class SalesShipment
{
public string No { get; set; }
public string CustomerNo { get; set; }
public string ItemNo { get; set; }
public string Description { get; set; }
public string Description2 { get; set; }
public string UoM { get; set; }
public decimal? Quantity { get; set; }
public DateTime? ShipmentDate { get; set; }
}

In next step, we have to define our service contract (interface). Our service will have a single method to retrieve shipments for a NAV instance and with a shipment date filter. The service contract will be defined as follows:

public interface INAVService
{
        
   [OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, 
BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = 
"getShipments?instance={NAVInstanceName}&date={shipmentDateFilter}"]
List<SalesShipment> GetShipments(string NAVInstanceName, string 
shipmentDateFilter); //Date format parameter: YYYY-MM-DD
}
The WCF service definition will implement the previously defined interface as follows:
public class NAVService : INAVService
{
}
The GetShipments method is implemented as follows:
public List<SalesShipment> GetShipments(string NAVInstanceName, string shipmentDateFilter)
{ 
try
{
DataAccessLayer.DataAccessLayer DAL = new  
DataAccessLayer.DataAccessLayer();
List<SalesShipment>  list = DAL.GetNAVShipments(NAVInstanceName, 
shipmentDateFilter);
return list;
}
catch(Exception ex)
{
// You can handle exceptions here…
throw ex;
}
}

This method creates an instance of a DataAccessLayer class (which we will discuss in detail later) and calls a method called GetNAVShipments by passing the NAV instance name and ShipmentDateFilter.

To call the NAV business logic, we need to have a reference to the NAV OData web service (only to generate a proxy class, the real service URL will be dynamically called by code) so right-click on your project (WCFServiceWebRoleNAV) and navigate to Add | Service Reference.

In the Add Service Reference window, paste the OData URL that comes from NAV and when the service is discovered, give it a reference name (here, it is NAVODATAWS).

Visual Studio automatically adds a service reference to your project.

The DataAccessLayer class will be responsible for handling calls to the NAV OData web service. This class defines a method called GetNAVShipments with the following two parameters:

  • NAVInstanceName: This is the name of the NAV instance to call
  • shipmentDateFilter: This filters date for the NAV shipment lines (greater than or equal to)

According to NAVInstanceName, the method retrieves from the web.config file (appSettings) the correct NAV OData URL and credentials, calls the NAV query (by passing filters), and retrieves the data as a list of SalesShipment records (our data model).

The DataAccessLayer class is defined as follows:

public List<SalesShipment> GetNAVShipments(string NAVInstanceName, string shipmentDateFilter)
{
try
{
string URL = 
Properties.Settings.Default[NAVInstanceName].ToString();

string WS_User = Properties.Settings.Default[NAVInstanceName + 
"_User"].ToString();

string WS_Pwd = Properties.Settings.Default[NAVInstanceName + "_Pwd"].ToString();

string WS_Domain = Properties.Settings.Default[NAVInstanceName + "_Domain"].ToString();

DataServiceContext context = new DataServiceContext(new Uri(URL));

NAVODATAWS.NAV NAV = new NAVODATAWS.NAV(new Uri(URL));
NAV.Credentials = new System.Net.NetworkCredential(WS_User, WS_Pwd, WS_Domain);

DataServiceQuery<NAVODATAWS.ItemShipments> q = NAV.CreateQuery<NAVODATAWS.ItemShipments>("ItemShipments");

if (shipmentDateFilter != null)
{
string FilterValue = string.Format("Shipment_Date ge datetime'{0}'", shipmentDateFilter);
q = q.AddQueryOption("$filter", FilterValue);
}

List<NAVODATAWS.ItemShipments> list = q.Execute().ToList();

List<SalesShipment> sslist = new List<SalesShipment>();

foreach (NAVODATAWS.ItemShipments shpt in list)
{
SalesShipment ss = new SalesShipment();
ss.No = shpt.No;
ss.CustomerNo = shpt.Sell_to_Customer_No;
ss.ItemNo = shpt.ItemNo;
ss.Description = shpt.Description;
ss.Description2 = shpt.Description_2;
ss.UoM = shpt.Unit_of_Measure;
ss.Quantity = shpt.Quantity;
ss.ShipmentDate = shpt.Shipment_Date;
sslist.Add(ss);
}

return sslist;
}
catch (Exception ex)
{
throw ex;
}
}

The method returns a list of the SalesShipment objects. It creates an instance of the NAV OData web service, applies the OData filter to the NAV query, reads the results, and loads the list of the SalesShipment objects.

Deployment to Azure App Service

Now that your service is ready, you have to deploy it to the Azure App Service by performing the following steps:

  1. Right-click on the NAVAzureCloudService project and select Package… as shown in the following screenshot:
  2. In the Package Azure Application window, select Service configuration as Cloud and Build configuration as Release, and then click on Package as shown in the following screenshot:
  3. This operation creates two files in the <YourProjectName>binReleaseapp.publish folder as shown in the following screenshot:

These are the packages that must be deployed to Azure. To do so, you have to log in to the Azure Portal and navigate to Cloud Services | Add from the hub menu at the left.

In the next window, set the following cloud service parameters:

  • DNS name: This depicts name of your cloud service (yourname.cloudapp.net)
  • Subscription: This is the Azure Subscription where the cloud service will be added
  • Resource group: This creates a new resource group for your cloud service or use existing one
  • Location: This is the Azure location where the cloud service is to be added

Finally, you can click on the Create button to create your cloud service.

Now, deploy the previously created cloud packages to your cloud service that was just created. In the cloud services list, click on NAVAZureCloudService, and in the next window, select the desired slot (for example, Production slot) and click on Upload as shown in the following screenshot:

In the Upload a package window, provide the following parameters:

  • Storage account: This is a previously created storage account for your subscription
  • Deployment label: This is the name of your deployment
  • Package: Select the .cspkg file previously created for your cloud service
  • Configuration: Select the .cspkg file previously created for your cloud service configuration

You can take a look at the preceding parameters in the following screenshot:

Select the Start deployment checkbox and click on the OK button at the bottom to start the deployment process to Azure.

Now you can start your cloud service and manage it (swap, scaling, and so on) directly from the Azure Portal:

When running, you can use your deployed service by reaching this URL:

http://navazurecloudservice.cloudapp.net/NAVService.svc

This is the URL that the HQAPP in our business scenario has to call for retrieving data from the various NAV instances of the subsidiary companies around the world.

In this way, you have deployed a service to the cloud, you can manage the resources in a central way (via the Azure Portal), and you can easily have different environments by using slots.

Summary

In this article, you learned to enable NAV instances placed at different locations to interact with an external application through Azure App Service and also the features that it provides.

Resources for Article:


Further resources on this subject:


Packt

Share
Published by
Packt

Recent Posts

Harnessing Tech for Good to Drive Environmental Impact

At Packt, we are always on the lookout for innovative startups that are not only…

2 months ago

Top life hacks for prepping for your IT certification exam

I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…

3 years ago

Learn Transformers for Natural Language Processing with Denis Rothman

Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…

3 years ago

Learning Essential Linux Commands for Navigating the Shell Effectively

Once we learn how to deploy an Ubuntu server, how to manage users, and how…

3 years ago

Clean Coding in Python with Mariano Anaya

Key-takeaways:   Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…

3 years ago

Exploring Forms in Angular – types, benefits and differences   

While developing a web application, or setting dynamic pages and meta tags we need to deal with…

3 years ago