43
Integrating Windows Phone 7 to Microsoft Dynamics NAV 2009R2 Eric Wauters 1 Development Manager iFacto Business Solutions NV Waldo’s blog (www.waldo.be)

Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Integrating Windows Phone 7 to Microsoft Dynamics NAV 2009R2

Eric Wauters

1

Development ManageriFacto Business Solutions NVWaldo’s blog (www.waldo.be)

Page 2: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

2

Integrating Windows Phone 7 to Microsoft Dynamics NAV 2009R2

Eric WautersBackup for Freddy Kristiansen

Page 3: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Agenda

• Cloud? What is that all about? We’re all in .. but in what?

• Building a Windows Phone app that connects to NAV using the cloud.

Page 4: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Cloud computing?

Cloud computing is a pay-per-use model for enabling available, convenient, on-demand network access to a shared pool of configurable computing resources (e.g., networks, servers,

storage, applications, services) that can be rapidly provisioned and released with minimal management effort or service

provider interaction.

Page 5: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Cloud Computing?

Page 6: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Cloud Computing?

Rapid elasticity

Pay per use

Location independent resource pooling

Standard network access

On-demand self-service

Char

acte

ristic

s

Page 7: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Enterprise Cloud Triggers – DriversSpeed to Value1

Flexibility2

Cross Organizational Collaboration3

Cost Reduction 4

CapEx Avoidance5

Green IT6

Page 8: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

CapEx Avoidance – Traditional IT

TIME

IT C

APAC

ITY

Actual Load

Allocated IT-capacities

“Waste“ of capacities

“Under-supply“ of capacities

Fixed cost of IT-capacities

Load Forecast

Barrier forinnovations

Page 9: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

CapEx Avoidance – Cloud

Actual Load

Allocated IT capacities

Reduction of initial

investments

Reduction of “over-supply“

No “under-supply“

Possible reduction of IT-

capacities in case of reduced

load

Time

IT C

APAC

ITY

Load Forecast

Page 10: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Microsoft Online Services Platform

ON-PREMISES

BUSINESS APPSCOLLABORATION STORAGE PLATFORMIDENTITYCOMMUNICATIONSPRODUCTIVITY

CLOUD SERVICES

Page 11: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

SERVICE ORDERS

Page 12: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Components in play

• NAV– Service Dispatchers RoleCenter– Customizations– Web Services, .net interop

• Proxy– C# Windows Service– Connecting to NAV Web Services– Exposing API on the Service Bus

• Windows Phone 7– Silverlight Application

• Cloud– Windows Azure Account

Page 13: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Windows AzureStorage

Service BusServices

Components - flow

NAVService

Tier

Firewall

Upload image

Register Notification

Channel

Window

s Auth

ProxySend Toast Notification

Services

Expose Proxy API on Azure AppFabric

Download image

Send Toast Notification

Get Service OrdersAccept Service Order

Change Order Status – In

ProcessChange Order Status –

FinishedAttach image URLAttach Note

Get Notification Channel Uri

Show map / Calculate route

Page 14: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

SERVICE ORDERS – DEMO?

Page 15: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

NAV customizations• Service Order card

– On Creating/Modifying Service Orders

• Send notifications (.net interop)

– Related Information – Images

• Download images from Azure storage

• Service Order Image table

• Exposes Web Services– For the Proxy

• Customer Card Page

• Service Order Card Page

• Special build Codeunit

NAVService

Tier

Page 16: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Windows Phone 7 Application• Connecting to NAV Web Services

– Via the Service Bus

• Get Service Orders

• Accept Service Order

• Change status on Service Order

• Attach images and notes to service orders

• Register notification channel (plumbing)

• Connecting to Azure Storage– To storage images

Page 17: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Windows Phone 7• Free Developer tools

– http://create.msdn.com/en-US/

– .net, C#, Silverlight

– Microsoft

• A TON of stuff on how to develop applications for Windows Phone already out there

Page 18: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Https Web Services Proxy - API

[ServiceContract]public interface IServiceOrderProxyClass{ [OperationContract] ServiceOrder[] GetServiceOrders(string username, string password);

[OperationContract] bool AcceptServiceOrder(string username, string password, string no);

[OperationContract] void ChangeServiceOrderStatus(string username, string password, string no, string status);

[OperationContract] void AttachServiceOrderImage(string username, string password, string no, string blobName);

[OperationContract] void AttachServiceOrderNote(string username, string password, string no, string note);

[OperationContract] void RegisterWp7ChannelUri(string username, string password, string channelUri);}

Page 19: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Https Web Services Proxy• Exposes endpoint on the Service Bus

• Connects to NAV Web Services

• Dedicated for Service Orders scenario

• Only expose necessary API– Isolating NAV from attacks

• Removes complexity

• Reduces roundtrips

• Loose coupling (device / NAV)– Possible to use other devices

Page 20: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Windows Azure Account• Windows Azure AppFabric (Service Bus)

– For communication between phone and on-premise NAV

• IssuerName, IssuerSecret

• Windows Azure Storage– For image storing / retrieving

• AccountName, AccessKey

Page 21: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

STEP BY STEPWalkthrough

Page 22: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Exposing an API on Windows Azure AppFabric

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Page 23: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Exposing an API on Windows Azure AppFabric

• Proxy– Create ServiceHost

– Add ServiceBus Endpoints

– Set Shared Secret credentials on endpoints

• IssuerName, IssuerSecret

– Start Servicehost

• Windows Azure AppFabric SDK– http://

www.microsoft.com/downloads/en/details.aspx?FamilyID=39856a03-1490-4283-908f-c8bf0bfad8a5

var serviceHost = new ServiceHost(new ServiceOrderProxyClass());

// sb:// bindingUri sbUri = ServiceBusEnvironment.CreateServiceUri("sb", "iFactoCloudDemo", instanceId);var sbBinding = new NetTcpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.None);serviceHost.AddServiceEndpoint(typeof(IServiceOrderProxyClass), sbBinding, sbUri);

// https:// binding (for Windows Phone etc.)Uri httpsUri = ServiceBusEnvironment.CreateServiceUri("https", "iFactoCloudDemo", "https/" + instanceId);var httpsBinding = new BasicHttpRelayBinding(EndToEndBasicHttpSecurityMode.Transport, RelayClientAuthenticationType.None);serviceHost.AddServiceEndpoint(typeof(IServiceOrderProxyClass), httpsBinding, httpsUri);

// Setup Shared Secret Credentials for hosting endpoints on the Service BusTransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();sharedSecretServiceBusCredential.CredentialType = TransportClientCredentialType.SharedSecret;sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName = issuerName;sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret = issuerSecret;

// Set credentials on all endpoints on the Service Busforeach (ServiceEndpoint endpoint in serviceHost.Description.Endpoints) endpoint.Behaviors.Add(sharedSecretServiceBusCredential);

serviceHost.Open();

Page 24: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Register Notification Channel

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Register Notification

Channel

Get Notification Channel Uri

Page 25: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

• Phone– Creates a NotificationChannel using Windows Phone API

– Invokes RegisterWp7ChannelUri in Proxy through Web Services

• Proxy– Authenticates phone user

– Invokes RegisterWp7ChannelUri in Codeunit through Web Services

• NAV – Update/Insert record in Wp7Channel table

Register Notification Channelpublic void RegisterWp7ChannelUri(string username, string password, string channelUri){ var service = new ServiceOrderRef.ServiceOrder(); Authenticate(service, username, password); service.RegisterWp7ChannelUri("ServiceOrders", channelUri);}

RegisterWp7ChannelUri(Application : Text[40];ChannelUri : Text[250])Wp7Channel.SETRANGE(UserID, USERID);Wp7Channel.SETRANGE(Application, Application);IF Wp7Channel.FINDFIRST THENBEGIN Wp7Channel.ChannelUri := ChannelUri; Wp7Channel.MODIFY();END ELSEBEGIN CLEAR(Wp7Channel); Wp7Channel.INIT(); Wp7Channel.UserID := USERID; Wp7Channel.Application := Application; Wp7Channel.ChannelUri := ChannelUri; Wp7Channel.INSERT();END;

... HttpNotificationChannel.Find("waldo.ServiceOrders"); if (myChannel == null) { myChannel = new HttpNotificationChannel("waldo.ServiceOrders"); } SendURIToService(myChannel.ChannelUri); ...

private void SendURIToService(Uri uri){ var client = App.GetServiceOrderProxyClient(); client.RegisterWp7ChannelUriAsync(App.Settings.UserName, App.Settings.Password, uri.AbsoluteUri);}

Page 26: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Send Notification

NAVService

Tier

Firewall

Service Bus

Wndow

s Auth

ProxyExpose Proxy API on Azure AppFabricSend Toast Notification

Send Toast Notification

Page 27: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Send Toast Notification• NAV

– Loop through Wp7Channel table

– Using a WP7Helper class to send the notification (.Net Interop)

• Create XML Document

• Error handling

• Send request using HttpWebRequest / HttpWebResponse

BroadcastToastNotification(Application : Text[40];Header : Text[40];Text : Text[40])Wp7Channel.SETRANGE(Wp7Channel.Application, Application);IF Wp7Channel.FINDSET THEN BEGIN REPEAT Wp7Notifications.DoSendToastNotification(Wp7Channel.ChannelUri,2,Header,Text); UNTIL Wp7Channel.NEXT = 0;END;

DoSendToastNotification(Wp7Channel : Record Wp7Channel;Priority : Integer;Text1 : Text[40];Text2 : Text[40])IF Wp7Channel.NextAttempt > CURRENTDATETIME THEN EXIT;status := Wp7Helper.SendToastNotification(Wp7Channel.ChannelUri, Priority, Text1, Text2);//MESSAGE(FORMAT(status));CASE status OF1: BEGIN // Invalid Uri Wp7Channel.DELETE(); END;2: BEGIN // Queue Full - Wait one hour before reattempting this Uri Wp7Channel.NextAttempt := CURRENTDATETIME + 3600000; Wp7Channel.MODIFY; END;3: BEGIN // Service Unavailable - Wait one hour before reattempting this Uri Wp7Channel.NextAttempt := CURRENTDATETIME + 3600000; Wp7Channel.MODIFY; END;END;

Page 28: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Get Service Orders

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Get Service Orders

Page 29: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

GetServiceOrders• Phone

– Invoke GetServiceOrders in Proxy through Web Services

• Proxy– Reads Service Orders from card page

• Assigned to me

• Assigned to nobody

– Builds and returns ServiceOrderProxyClass collection

• With Customer info read from Customer Card

• Phone– Calculate distance from current location to each service location

– Update Collections (assigned, prioritized, closest)

private double CalculateDistance(double lat1, double lon1, double lat2, double lon2, char unit){ double theta = lon1 - lon2; double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta)); dist = rad2deg(Math.Acos(dist)) * 60 * 1.1515; if (unit == 'K') dist = dist * 1.609344; return (dist);}

private double deg2rad(double deg){ return (deg * Math.PI / 180.0);}

void LoadServiceOrders(){ var client = App.GetServiceOrderProxyClient(); client.GetServiceOrdersCompleted += new EventHandler<ServiceOrderProxy.GetServiceOrdersCompletedEventArgs>(client_GetServiceOrdersCompleted); client.GetServiceOrdersAsync(App.Settings.UserName, App.Settings.Password);}

void client_GetServiceOrdersCompleted(object sender, ServiceOrderProxy.GetServiceOrdersCompletedEventArgs e){ this.All.Clear(); foreach (ServiceOrderProxy.ServiceOrder serviceOrder in e.Result) { serviceOrder.Distance = CalculateDistance(CurrentLocation.Latitude, CurrentLocation.Longitude, serviceOrder.Latitude, serviceOrder.Longitude, unit); this.All.Add(serviceOrder); } UpdateCollections();}

public ServiceOrder[] GetServiceOrders(string username, string password){ ... var myFilter = new ServiceOrderCardRef.ServiceOrderCard_Filter(); myFilter.Field = ServiceOrderCardRef.ServiceOrderCard_Fields.Assigned_User_ID; myFilter.Criteria = "@" + service.GetMyUserID(); var myFilters = new ServiceOrderCardRef.ServiceOrderCard_Filter[] { myFilter }; var myOrders = serviceOrderService.ReadMultiple(myFilters, null, 0);

var unassignedFilter = new ServiceOrderCardRef.ServiceOrderCard_Filter(); unassignedFilter.Field = ServiceOrderCardRef.ServiceOrderCard_Fields.Assigned_User_ID; unassignedFilter.Criteria = "=''"; var unassignedFilters = new ServiceOrderCardRef.ServiceOrderCard_Filter[] { unassignedFilter }; var unassignedOrders = serviceOrderService.ReadMultiple(unassignedFilters, null, 0);

var serviceOrders = new ServiceOrder[myOrders.Length + unassignedOrders.Length]; for (int i = 0; i < myOrders.Length; i++) serviceOrders[i] = ServiceOrder.CreateServiceOrderClass(myOrders[i], customerCardService.Read(myOrders[i].Customer_No));

for (int i = 0; i < unassignedOrders.Length; i++) serviceOrders[i + myOrders.Length] = ServiceOrder.CreateServiceOrderClass(unassignedOrders[i], customerCardService.Read(unassignedOrders[i].Customer_No)); return serviceOrders;}

Page 30: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Accept Service Order

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Accept Service Order

Page 31: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

• Phone– Ask user if he wants to accept the Service Order

– Invoke AcceptServiceOrder in Proxy through Web Services

• Proxy– Read the Service Order from the Card Page through Web Services

– If the Service Order is assigned already – return false

– Set the Assigned_User_ID

– Write the Service Order again – if error – return false

• Phone– Display message and refresh data

Accept Service Order

void acceptAction_Click(object sender, EventArgs e){ if (MessageBox.Show("Do you want to accept this Service Order?", "Accept", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { var client = App.GetServiceOrderProxyClient(); client.AcceptServiceOrderCompleted += new EventHandler<ServiceOrderProxy.AcceptServiceOrderCompletedEventArgs>(client_AcceptServiceOrderCompleted); client.AcceptServiceOrderAsync(App.Settings.UserName, App.Settings.Password, this.ServiceOrder.No); } }

public bool AcceptServiceOrder(string username, string password, string no){ var service = new ServiceOrderRef.ServiceOrder(); Authenticate(service, username, password);

var serviceOrderService = new ServiceOrderCardRef.ServiceOrderCard_Service(); Authenticate(serviceOrderService, username, password);

var serviceOrder = serviceOrderService.Read(no); if (!string.IsNullOrEmpty(serviceOrder.Assigned_User_ID)) return false; serviceOrder.Assigned_User_ID = service.GetMyUserID(); try { serviceOrderService.Update(ref serviceOrder); return true; } catch { return false; }}

void client_AcceptServiceOrderCompleted(object sender, ServiceOrderProxy.AcceptServiceOrderCompletedEventArgs e){ Deployment.Current.Dispatcher.BeginInvoke(() => { if (e.Result) { MessageBox.Show("ServiceOrder is now assigned to you!"); this.AssignedToMe = true; } else MessageBox.Show("ServiceOrder was already assigned to someone else"); App.ViewModel.LoadData(); UpdateApplicationBarButtons(); });}

Page 32: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Change Service Order Status

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Change Service Order

Status

Page 33: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Change Service Order Status• Phone

– Change status on Service Order internally

– Invoke ChangeServiceOrderStatus in Proxy through Web Services

• Proxy– Read Service Order from the Card Page through Web Services

– Set the Status

– Update Starting Date/Time or Finishing Date/Time if necessary

– Write the Service Order again

private void ChangeServiceOrderStatus(ServiceOrderProxy.ServiceOrder serviceOrder, string status){ serviceOrder.Status = status; var client = App.GetServiceOrderProxyClient(); client.ChangeServiceOrderStatusAsync(App.Settings.UserName, App.Settings.Password, serviceOrder.No, status);}

public void ChangeServiceOrderStatus(string username, string password, string no, string statusStr){ var serviceOrderService = new ServiceOrderCardRef.ServiceOrderCard_Service(); Authenticate(serviceOrderService, username, password);

var status = (Status)Enum.Parse(typeof(Status), statusStr.Replace(' ', '_'), true); var serviceOrder = serviceOrderService.Read(no); serviceOrder.Status = status; serviceOrderService.Update(ref serviceOrder);}

Page 34: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Capture and Upload Image

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Storage

Upload image

Page 35: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Capture and upload Image• Delay’s Blog

– http://blogs.msdn.com/b/delay/

– Blob API for Windows Phone 7

• Ms-PL (http://opensource.org/licenses/ms-pl.html)

• Phone– Capture Image

– Resize image

• to save time when uploading

– Upload image to Azure Storage

void cameraTask_Completed(object sender, PhotoResult e){ if (e.TaskResult == TaskResult.OK) { // Using WriteableBitmap's SaveJpeg to resize var bitmapImage = new BitmapImage(); bitmapImage.SetSource(e.ChosenPhoto); var bitmap = new WriteableBitmap(bitmapImage); var ms = new MemoryStream(); bitmap.SaveJpeg(ms, 1024, 768, 0, 90); var photo = ms.ToArray();

// Upload photo blobClient = new AzureBlobStoreClient(AzureStorageAccountName, AzureStoragePrimaryAccessKey, "images"); blobInfo = new BlobInfo(Guid.NewGuid().ToString()); blobClient.PutBlob(blobInfo, photo.Length, (s) => PutBlobAction(s, photo), PutBlobCompleted, (ex) => PutBlobFailed(ex)); }}

... CameraCaptureTask cameraTask; ... cameraTask = new CameraCaptureTask(); cameraTask.Completed += new EventHandler<PhotoResult>(cameraTask_Completed); ...

void cameraAction_Click(object sender, EventArgs e){ cameraTask.Show(); //shows camera to take the picture}

void PutBlobAction(Stream s, byte[] photo){ s.Write(photo, 0, photo.Length);}

void PutBlobCompleted(){ Deployment.Current.Dispatcher.BeginInvoke(() => AttachServiceOrderImage(this.ServiceOrder, blobInfo.Name));}

private void PutBlobFailed(Exception ex){ Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show("No connectivity.”));}

Page 36: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Attach Image / Note

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Attach Image / Note

Storage

Page 37: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Attach Image / Note• Phone

– Invoke AttachServiceOrderImage/Note in Proxy through Web Services with Uri to Azure Storage blob or note

– Display message box when image uploaded

• Proxy– Invoke AttachServiceOrderImage/Note in NAV Codeunit through Web

Services with Uri or note

• NAV– Insert Image Uri in ServiceOrderImage Table or add note to RecordLink

table

private void AttachServiceOrderImage(ServiceOrderProxy.ServiceOrder serviceOrder, string blobName){ var client = App.GetServiceOrderProxyClient(); client.AttachServiceOrderImageCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_AttachServiceOrderImageCompleted); client.AttachServiceOrderImageAsync(App.Settings.UserName, App.Settings.Password, serviceOrder.No, blobName);}

void client_AttachServiceOrderImageCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e){ Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show("Image uploaded.")); }

private void Save_Click(object sender, EventArgs e){ var client = App.GetServiceOrderProxyClient(); client.AttachServiceOrderNoteAsync(App.Settings.UserName, App.Settings.Password, ID, this.textBox1.Text); NavigationService.GoBack();}

public void AttachServiceOrderImage(string username, string password, string no, string blobName){ var service = new ServiceOrderRef.ServiceOrder(); Authenticate(service, username, password); service.AttachServiceOrderImage(no, blobName);}

public void AttachServiceOrderNote(string username, string password, string no, string note){ var service = new ServiceOrderRef.ServiceOrder(); Authenticate(service, username, password); service.AttachServiceOrderNote(no, note);}

AttachServiceOrderImage(No : Code[20];Image : Text[40])ServiceOrderImage.INIT;ServiceOrderImage."Document No." := No;ServiceOrderImage."Image ID" := Image;ServiceOrderImage.INSERT(TRUE);

AttachServiceOrderNote(No : Code[20];Note : Text[250])ServiceHeader.GET(ServiceHeader."Document Type"::Order, No);RecRef.GETTABLE(ServiceHeader);RecordLink.INIT();RecordLink.Type := RecordLink.Type::Note;RecordLink.Created := CURRENTDATETIME;RecordLink."User ID" := USERID;RecordLink.URL1 := 'dynamicsnav://freddyk-appfabr:7047/DynamicsNAV/'+COMPANYNAME+'/runpage?page=5900&personalization=5900&'+ 'bookmark='+FORMAT(RecRef.RECORDID,0,10)+'&mode=edit';RecordLink.Description := 'Service Order - '+No;RecordLink.Company := COMPANYNAME;RecordLink."Record ID" := RecRef.RECORDID;CLEAR(RecordLink.Note);Note := ' '+Note;Note[1] := STRLEN(Note)-1;NoteText.ADDTEXT(Note);RecordLink.Note.CREATEOUTSTREAM(NoteStream);NoteText.WRITE(NoteStream);RecordLink.INSERT();

Page 38: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

Download and display image

NAVService

Tier

Firewall

Service Bus

Window

s Auth

ProxyExpose Proxy API on Azure AppFabric

Storage

Download image

Page 39: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

• NAV– Create .net class AzureStorage

• Using AccountName and AccessKey

• Wrapper for AzureBlobStoreClient (Delay’s Blog)

– Download all blobs for a specific Service Order to the Service Tier

– Use File.Download to show images on the Client

Download and display image

<Action1170000001> - OnAction()AzureStorage := AzureStorage.AzureStorage(AzureStorageAccountName, AzureStorageAccessKey);ServiceOrderImage.SETRANGE(ServiceOrderImage."Document No.", "No.");IF NOT ServiceOrderImage.FIND('-') THENBEGIN MESSAGE('No Images attached');END ELSEREPEAT AzureStorage.GetBlob('images', ServiceOrderImage."Image ID", TEMPORARYPATH+ServiceOrderImage."Image ID"+'.jpg'); toFile := ServiceOrderImage."Image ID"+'.jpg'; FILE.DOWNLOAD(TEMPORARYPATH+ServiceOrderImage."Image ID"+'.jpg', 'Service Order Image','', '', toFile);UNTIL ServiceOrderImage.NEXT = 0;

public class AzureStorage{ string AccountName; string AccessKey;

public AzureStorage(string AccountName, string AccessKey) { this.AccountName = AccountName; this.AccessKey = AccessKey; }

public void GetBlob(string container, string name, string filename) { EnsureContainerIsCreated(container); var blobClient = new AzureBlobStoreClient(AccountName, AccessKey, container); var blobInfo = new BlobInfo(name); blobClient.GetBlob(blobInfo, (s) => GetBlobAction(s, filename)); }

...

Page 40: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters
Page 41: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

44

More info

• Will soon be published on:– http://blogs.msdn.com/b/freddyk

• Related info:– Vjeko’s blog (navigateintosuccess.com)

– Waldo’s blog (www.waldo.be)

– Mibuso

– Dynamicsuser.net

– ...

Page 42: Dynamics NAV, Windows Azure & Windows Phone 7, Eric Wauters

45

Questions?