Philippsen's Blog

Everyday findings in my world of .net and related stuff

Wrapping a webservice in a .net assembly for Dynamics AX

Posted by Torben M. Philippsen on July 4, 2012

As for Dyanamics AX 2009 I quite often bump into problems when trying to consume external webservices inside Dynamics AX.

The problems that I’ve experienced often relates either to the WSDL causing AX to throw an CLR error when trying to add a service reference or if the webservice requires authentication or similar, which is not possible to configure/set within AX.

The workaround that has shown to come in handy numerous times, is to create a webservice wrapper in .net and having that wrapper added as a reference in the AOT.
In order to be able to perform this task, You will need to do as follows:

  1. Create a new library project in Visual Studio
  2. Add a service reference to you WSDL file. In “advanced settings” make sure that the “Access level for generated classes” is set to “public”.
  3. compile the DLL
  4. Copy the dll to the client bin folder.
    This procedure is primarily only necessary in order to being able to select the assembly from the AOT or if You want to be able to use the assembly from AX clients.
  5. Copy and rename the corresponding *.config file as “ax32.exe.config”. If the file already exist, merge the content of Your file with the existing one.
  6. Copy the dll to the AX server (AOS) bin folder.
  7. Copy and rename the corresponding *.config file as “ax32serv.exe.config”. If the file already exist, merge the content of Your file with the existing one.
  8. test using the dll from client side jobs. you can leave this out, if You’re only going to use the assmebly from server side operations.
  9. test using the dll from server side classes.

Ofcource there is always pros and cons when dealing with workarounds…

Cons:

  • a slight increase in complexity when dealing with components outside AX.
  • You need to remember to copy the dll to new AOS instances if you in the future are adding new ones to Your setup.
  • some people don’t like to have code residing outside AX

Pros:

  • The abilty to access proxy properties that aren’t normally exposed to AX – eg. “ClientCredentials”.
  • when a wsdl fails to be added as a service reference in AX you will most likely not experience the same problems from .net. This means that You could either try to have the webservice changed into something more AX friendly (good luck with that) or you could just simply choose/be forced to use this workaround;-)

Posted in Microsoft Dynamics AX, Webservices | Tagged: , , | Leave a Comment »

UAC troubles

Posted by Torben M. Philippsen on June 12, 2012

Working with UAC (User Access control) in relation to win vista, win7 and win server 2008 can be quite troublesome.
Yesterday we found that one our helper apps, which has a feature to start and stop services both local and remotely, didn’t work as expected. When running the application in elevated mode, everything worked fine.
Since we can’t expect all users to remember to run the application in elevated mode, we needed to find a more permanent solution.
I have previously been working with UAC problems relating to processes not running in elevated mode, but i didn’t know how to force the entire application ro run in elevated mode. Google turned out to be my friend again and I found tons of articles telling me “just” to add a manifest file changing the existing:
<requestedExecutionLevellevel=asInvokeruiAccess=false />

to:

<requestedExecutionLevellevel=requireAdministratoruiAccess=false />

Simple one would think – and it was, so You might figure my level of frustration, when this turned out not  to be enough.

Actually there was nothing wrong with the suggested solution, but all post that I read, failed to explain how to tell Visual Studio to use the added manifest file – I had to figure that out myself. A complete solution on how to force Your application to always run in elevated mode wil be listed here:

  • In Visual Studio 2010 (I guess the same applies to VS2008, but I haven’t tested it) right click Your project and select “add new item”
  • Add a application manifest file – the default name will be app.manifest.
  • Inside the manifest file, change the existing configuration from
    <requestedExecutionLevellevel=”asInvoker”uiAccess=”false” />
    To
    <requestedExecutionLevellevel=”requireAdministrator”uiAccess=”false” />
  • Save and close the manifest file.
  • Please note that Your manifest file won’t show up anywhere in your solution. In order to fix that, in solution explorer, click the “show all files” button.
  • Important: Right click the manifest file and add it to the project – we need that in order to tell VS to use the manifest file when compiling our application.
  • Right click Your project and select “properties”.
  • On the application tab, the bottom section, select the manifest file:

    manifest file selection

    manifest file selection

  • Compile and run the application. If Your UAC settings are enabled, You will be prompted to allow the application to start in elevated mode.

Sometimes it can come in handy to check whether Your application is actually running in elevated mode or not. Maybe You will find this codesnippet usefull:

 WindowsPrincipal myPrincipal = new WindowsPrincipal (WindowsIdentity .GetCurrent());

 if (myPrincipal.IsInRole(WindowsBuiltInRole .Administrator) == false )
 {
  //show messagebox - displaying a messange to the user that rights are missing
  MessageBox .Show("You need to run the application using the \\"run as administrator\\" option" , "administrator right required" , MessageBoxButtons .OK, MessageBoxIcon .Exclamation); 
 }
 else
 {
  MessageBox .Show("You are good to go - application running in elevated mode" , "Good job" , MessageBoxButtons .OK, MessageBoxIcon .Information);
 }

You may also find these references helpfull:

http://stackoverflow.com/questions/2818179/how-to-force-c-sharp-app-to-run-as-administrator-on-windows-7

http://msdn.microsoft.com/en-us/library/bb756929.aspx

http://victorhurdugaci.com/using-uac-with-c-part-1/

Posted in Books and reading stuff, Microsoft .net, Visual Studio | Tagged: , , , , , | Leave a Comment »

Enterprise Portal development (AX 2009) – the basics

Posted by Torben M. Philippsen on May 15, 2012

Sometimes I find myself struggling with a lot of basic stuff when wanting to do some EP related development. In order to spare me  (and hopefully others) some time in the future, I decided to create this article.

Step 1 – the prerequisites:

Generally You can save Yourself a lot of trouble if Enterprise Portal is installed on the same server as Your development environment (Visual Studio). If possible, You should also consider to have EP set up on a 32 bit platform – meaning that the OS and Windows Sharepoint Services (WSS) is running in 32 bit mode.

In matters of EP development, running on 64 bit platform is the mother of all evil – examples on this will follow…

Enterpise Portal development tools must be installed. This can be done from the installation medias.

Generally the EP dev tools installs EP project- and control templates. Please note that the EP dev tools should be installed after installing Visual Studio 2008 – if not, the VS templates will most likely not be installed correctly. To ensure that the EP dev tools are successfully installed and that the Dynamics AX web project template is available from within Visual Studio, please do the following:

The Web Site project template AxWebProject.zip is installed in My Documents folder under Visual Studio 2008\Templates\ProjectTemplates\Visual Web Developer\CSharp and page and control templates AxWebpartPage.zip and AxWebUserControl.zip under Visual Studio 2008 \Templates\ItemTemplates\Visual Web Developer\CSharp.

If these files are not found under Your user profile, You will have to copy them from the user who installed the EP dev tools.

The Add-in is installed in Program Files\Microsoft Dynamics AX\50\EnterprisePortalTools and is added to the VS Add-in files path and enabled.

  1. You can check this in VS Tools->Options->Environment->Add-in/macros security, you should see

    Visual Studio Options dialog

    Visual Studio Options dialog

  2. In VS Tools -> Add-In Manager Dynamics AX Enterprise Portal Tools must be enabled.

    Visual Studio Add In manager dialog

    Visual Studio Add In manager dialog

To check if everything is installed corrected, when you create a new Web Site Project in VS 2008 C#, you should see Dynamics AX Web project template. After creating the project, in the solution explorer when you right click on app_code folder you should get Generate Proxies menu option.

Reference article: http://blogs.msdn.com/b/solutions/archive/2008/08/09/ep-visual-studio-add-in.aspx

Once this has been verified everything is good to go, but before firing up Visual Studio, You should check in which layer VS connects to AX. VS uses the business connector when connecting to AX. This means that You have to check that the BC is connecting to the layer of Your choice. In my case, we always use the CUS layer. By default the BC connects to AX using the USR layer. If You want to change this do the following:

  • On the server where EP is installed, click the “Start” button in Windows. Select “administrative tools” and enter the “Microsoft Dynamics AX Configuration Utility”.
  • Change the “Configuration Target” to “Business Connector”.

Select the “Developer” tab and change the “Application object layer to open” to “CUS” (or whatever You want) Remember to fill in the license code for that layer

DAX Configuration utility

DAX 2009 Configuration utility

Step 2 – Understanding proxies:

In order to being able to reference common AX types (Objects from the AOT – Classes, tables, methods and enums) AX needs to generate proxies for the objects that You want to use. These objects are defined in the AOT from Web->Web files->Static files->proxies. If You want other objects to be recognized by EP and Visual Studio, You need to edit this file manually. A guide how to do that can be found here:
http://msdn.microsoft.com/en-us/library/cc568275(v=ax.50).aspx

To deploy the proxies to EP, please do the following:

  • From the Microsoft Dynamics AX menu click Tools -> Development Tools-> Web development -> Proxies.

In the “Generate Proxies” window You will find two options for deploying the proxies

DAX Generate Proxies Dialog

DAX Generate Proxies Dialog

Step 3 – Visual Studio

A new user control is easily created by right clicking Your project node and selecting “Add new item”. From the “Add new item” dialog choose “Dynamics AX user control

Visual Studio Add new item dialog

In order to add the new user control to the AOT. Right click the control and select “Add to AOT”.

Once added to the AOT changes to the control will automatically be submitted to AX. Once AX recognizes a change AX will update the control automatically on the EP site. However if running in 64 bit mode, this will not work! You can work around this in two ways:

  1. From a command prompt You can run the D:\Microsoft Dynamics AX\50\Setup\AxUpdatePortal.exe command. (The file may be located elsewhere in Your environment). Running this command will deploy all web related changes to all EP sites.
    http://msdn.microsoft.com/en-us/library/dd261467(v=ax.50).aspx
  2. Running the AXUpdatePortal command may be very timeconsuming. You may find it more useful to manually copy Your usercontrol  to Your EP site. The default path for the EP site is: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS\ep. You may want to consider writing a small script to help You automate this process just a little bit.

Step 4 – Debugging in Visual Studio

Ofcourse You will want to be able to debug Your  code from within Visual Studio. In order to do so, there are a few things You need to know:

  • Changes made to your usercontrols are automatically updated at the EP site when running on a 32 bit platform. If running on a 64 bit platform, You will have to update EP manually. The process for doing so is described above.

You will have to change the debugging start options. Right click Your project and select “properties->Start options”. In the start options dialog enable the “start url” radio button:

Visual Studio Debugger Start Options

Visual Studio Debugger Start Options

and fill in the complete url for the page You want to hit on startup. This page is best found by browwing the actual EP site.
In the “use custom server” fill in the base url for the EP site. This can be fetched from within AX by entering  administration->Setup->Internet->Enterprise portal->web sites

Common issues

One of the most annoying things about working with EP related development is that You may quite often experience that EP causes Visual Studio to crash

EP Tools causes VS to crash

EP Tools causes VS to crash

The only working fix that I know of, is to create a new solution/website and have Your content transferred to that website. When the problem reoccurs the procedure has to be repeated – pretty annoying. If You know of a better workaround or maybe even a fix, please let me know.

Posted in Enterprise Development, Microsoft Dynamics AX | Tagged: , , | 1 Comment »

Business Connector isssues

Posted by Torben M. Philippsen on January 27, 2012

In a webservice I am using the Microsoft.DynamicsBusinessConnectorNet.dll. Today the webservice stopped working giving the error:

Could not load file or assembly ‘Microsoft.Dynamics.BusinessConnectorNet’

This was quite strange since the service was working yesterday. The reason to the error turned out to be a new deployment of a new webapplication to the IIS. This particular webapplication required the IIS to run in 64 bit mode and therefore this was changed. The Microsoft.DynamicsBusinessConnectorNet.dll that I was using was the 32bit version – which ofcourse was the cause of the error.

The solultion was to enable the application pool to allow 32 bit application. This is done by:

  • Right clicking the application pool and selecting “advanced setting”
  • Set the “enable 32-bit applicataions” to true

Her’s a screendump:

Enable 32 bit applicaations in IIS

Enable 32 bit applicaations in IIS

 

Update 2012-11-27: When enabling 32 bit applications on IIS6 I recently encountered that one need to run aspnet_regiis.exe in order to register the 32 bit version of the .net framework – otherwise I received a “servive not available” message

Posted in IIS | Tagged: , , , | Leave a Comment »

WSDL validation

Posted by Torben M. Philippsen on January 2, 2012

When consuming webservice from other vendors it often can come in handy to have their wsdl validated – just to rule out errors related to failure in validation.

I have found these validation sites to be very usefull:

Posted in WCF (Windows Communication Foundation) | Tagged: | Leave a Comment »

Very helpful blogpost on debuggig AIF services on a server 2008

Posted by Torben M. Philippsen on December 7, 2011

http://www.ksaelen.be/wordpress/2010/07/debugging-aif-on-windows-2008-2/

Posted in Books and reading stuff | Leave a Comment »

If the ‘nillable’ attribute is false in the schema, the ‘xsi:nil’ attribute must not be present in the instance

Posted by Torben M. Philippsen on December 2, 2011

If you recieve an error like this:

Invalid document schema. The following error was returned: If the ‘nillable’ attribute is false in the schema, the ‘xsi:nil’ attribute must not be present in the instance.

when submitting an AIF message, the most probably cause is that a field is required according to the datapolicies whilst You are sending in a null value. The solution is obviously to remove the “required” option in the datapolicies or to send in a value other than null:-)

Posted in AIF, Microsoft Dynamics AX | 1 Comment »

Digging into AIF

Posted by Torben M. Philippsen on November 29, 2011

Given my experiance in WCF I recently had the pleasure to dig into AIF (the Application Integration Framework in Dynamics AX).

As a newbie I quickly had to learn my lessons – and to avoid having to learn the same lessons twice I decided to add this post:-)

Initially I had to realize that these questions needed an answer:

  • Inside Dynmics AX – what is an endpoint?
  • Inside AX – what’s the idea of having local endpoints along with endpoints – what’s the difference?
  • How do I target a specific company?
  • How do I configure my .net client to use a certain AX endpoint?
  • How do I make sure that a certain datapolicy is actually applied to incoming messages?

In my examples I will use the build in LedgerPurchaseInvoiceService.

Asuming that this service has been enabled in “basic -> setup -> Application Integration Framework -> services” go to “basic -> setup -> Application Integration Framework -> endpoints”. There You will at least find the default Endpoint. AX uses the “Default Endpoint” as the destination endpoint and the local endpoint of the user calling the service for processing WCF requests. I wanted to be able to specify which endpoints my requests were using in order to take advantage of the security and processing features in AIF, This means that if no endpoint is specified from the client side when sending messages through AIF, the default endpoint is used. This also means that if You configure Your own endpoints these need to be specified from the client side…

We need to answer some of the questions above:

  1. What is an endpoint?
    Well I will try to explain this in my own terms… An endpoint is the single point of entry that is used from the client side. An endpoint is associated to a company which means if you configure an endpoint in company “A” you won’t be able to use that endpoint from comapny “B”.
    The endpoint is where you define the datapolicies – which fields are enabled, which fields are required and so on…
    An endpoint is based on a local endpoint.
  2. What’s the idea of having local endpoints?
    Local endpoints are global:-) This means that any of the local endpoints are visible through out all companies. A local endpoint is used to point to a certain company. Which brings us to question number 3
  3. If I want to target a certain company from the client side I will have to point to an endpoint configured in that company that uses a local endpoint associated to the same company.
    endpoints

    endpoints

    local_endpoints

    local_endpoints

    In my case I want to use the “SignFlow” endpoint from the client – which brings us to question number 4

  4. How do I configure my .net client to use a certain AX endpoint?
    The  magic word is “SOAP Headers”. Before calling any of the functions of your client object. You need to specify the destination endpoint, the sourceEndpoint and the sourceEndpointUser. The last two headers requires that You use a binding type that supports WS-Addressing.
    To add the SOAP Header You do the following:
 			PurchaseInvoiceServiceClient client = new PurchaseInvoiceServiceClient ();
 			try
 			{
 				//SOAP header info
 				using (new OperationContextScope (client.InnerChannel))
 				{
 					//CREATE HEADER TO SET SOURCE ENDPOINT
 					//this assumes that a endpoint (inside AX) with the name [SignFlow] has been created for all companies
 					SetDestinationEndpoint(ddlDataAraeId.SelectedValue);
 					//CREATE HEADER TO SET TARGET COMPANY
 					//this assumes that a local endpoint (inside ax) with the name [ddlDataAraeId.SelectedValue] has been configured
 					//and is associated with a company that exists in dynamics ax
 					SetSourceEndpointAndUser("SignFlow" );
 					//submit the request and retrieve the respons 
 					keys = client.create(recordWrapper);
 				}
 			}

 		/// <summary>
 		/// Helper method - adds a SOAP Header defining the destination endpoint (local endpoint) in Dynamics AX
 		/// </summary>
 		/// <param name="nameOfEndpoint">The name of the local endpoint</param>
 		private void SetDestinationEndpoint(string nameOfEndpoint)
 		{
 				OperationContext .Current.OutgoingMessageHeaders.Add(MessageHeader .CreateHeader("DestinationEndpoint" , "http://schemas.microsoft.com/dynamics/2008/01/services" , nameOfEndpoint)); 
 		}

 		/// <summary>
 		/// Helper method - adds a SOAP Header defining the source endpoint name and the source endpoint user to use
 		/// </summary>
 		/// <param name="sourceEndpointName">the name of the source endpoint</param>
 		private void SetSourceEndpointAndUser(string sourceEndpointName)
 		{
 			string userName = HttpContext .Current.User.Identity.Name.ToString(); //returns the current user and domian - eg. domainname\\username
 			var addressHeader = AddressHeader .CreateAddressHeader("SourceEndpointUser" , "http://schemas.microsoft.com/dynamics/2008/01/services" , userName);
 			var addressBuilder = new EndpointAddressBuilder (
 			new EndpointAddress (new Uri ("urn:" + sourceEndpointName), addressHeader));
 			var endpointAddress = addressBuilder.ToEndpointAddress();
 			OperationContext .Current.OutgoingMessageHeaders.From = endpointAddress;
 		}

The entire client code looks like this:

 using System;
 using System.Web;
 using System.Web.UI;
 using System.ServiceModel;
 using System.ServiceModel.Channels;
 using SignFlowIntegration.EG_InitialPurchaseInvoiceReg;

 namespace SignFlowIntegration
 {
 	public partial class InitialReg : System.Web.UI.Page
 	{
 		private enum DataAreaIdCollection { SVE, DMO, DAT, LON, MAS, FIN };
 		private enum CurrencyCodeCollection { DKK, AUD, CHF, CAD, EUR, GBP, NOK, SEK, USD, PLN };
 		protected void Page_Load(object sender, EventArgs e)
 		{
 			if (!Page.IsPostBack)
 			{
 				ddlDataAraeId.DataSource = System.Enum .GetValues(typeof (DataAreaIdCollection ));
 				ddlCurrencyCode.DataSource = System.Enum .GetValues(typeof (CurrencyCodeCollection ));
 				ddlDataAraeId.DataBind();
 				ddlCurrencyCode.DataBind();
 			}
 		}

 		/// <summary>
 		/// Handles the submit button click event
 		/// </summary>
 		/// <param name="sender"></param>
 		/// <param name="e"></param>
 		protected void btnSubmit_Click(object sender, EventArgs e)
 		{
 			decimal amountCur;
 			DateTime documentDate;
 			//create the client
 			PurchaseInvoiceServiceClient client = new PurchaseInvoiceServiceClient ();
 			//create wrapper for record object
 			AxdPurchaseInvoice recordWrapper = new AxdPurchaseInvoice ();
 			//create record objects
 			AxdEntity_LedgerJournalTable ledgerJournalTableObj = new AxdEntity_LedgerJournalTable ();
 			AxdEntity_LedgerJournalTrans ledgerJournalTransObj = new AxdEntity_LedgerJournalTrans (); 
 			//-----------------------------------------
 			//step 1
 			//-----------------------------------------
 			//assign values to record objects
 			ledgerJournalTableObj.JournalName = txtJournalName.Text;
 			ledgerJournalTableObj.JournalTypeSpecified = true ;
 			ledgerJournalTableObj.JournalType = AxdEnum_LedgerJournalType .PurchaseLedger;
 			ledgerJournalTransObj.AccountNum = txtAccountNum.Text;
 			ledgerJournalTransObj.EG_SignFlowCaseId = txtSignFlowsagsnr.Text;
 			if (DateTime .TryParse(txtDocumentDate.Text, out documentDate))
 			{
 				//set documentdate
 				ledgerJournalTransObj.DocumentDate = documentDate;
 			}
 			else
 			{
 				//default
 				ledgerJournalTransObj.DocumentDate = DateTime .Now;
 			}
 			ledgerJournalTransObj.CurrencyCode = ddlCurrencyCode.SelectedValue;
 			ledgerJournalTransObj.ApprovedBy = txtApprovedBy.Text;
 			ledgerJournalTransObj.Invoice = txtInvoice.Text;
 			if (decimal .TryParse(txtAmountCurCredit.Text, out amountCur))
 			{
 				ledgerJournalTransObj.AmountCurCreditSpecified = true ;
 				ledgerJournalTransObj.AmountCurCredit = amountCur;
 			}
 			else if (decimal .TryParse(txtAmountCurDebit.Text, out amountCur))
 			{
 				ledgerJournalTransObj.AmountCurDebitSpecified = true ;
 				ledgerJournalTransObj.AmountCurDebit = amountCur;
 			}
 			else
 			{
 				//default
 				ledgerJournalTransObj.AmountCurCreditSpecified = true ;
 				ledgerJournalTransObj.AmountCurCredit = 0;
 			}
 			//-----------------------------
 			//step 2 - add record to wrapper
 			//-----------------------------
 			recordWrapper.LedgerJournalTable = new AxdEntity_LedgerJournalTable [1]; 
 			ledgerJournalTableObj.LedgerJournalTrans = new AxdEntity_LedgerJournalTrans [1];
 			ledgerJournalTableObj.LedgerJournalTrans[0] = ledgerJournalTransObj;
 			recordWrapper.LedgerJournalTable[0] = ledgerJournalTableObj;
 			//Set impersonation level
 			client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel .Impersonation;
 			//prepare the repons object
 			EntityKey [] keys = new EntityKey [1];
 			//--------------------------------------
 			//step 3 - call create method on service
 			//add proper error handling
 			//--------------------------------------

 			try
 			{
 				//SOAP header info
 				using (new OperationContextScope (client.InnerChannel))
 				{
 					//CREATE HEADER TO SET SOURCE ENDPOINT
 					//this assumes that a endpoint (inside AX) with the name [SignFlow] has been created for all companies
 					SetDestinationEndpoint(ddlDataAraeId.SelectedValue);
 					//CREATE HEADER TO SET TARGET COMPANY
 					//this assumes that a local endpoint (inside ax) with the name [ddlDataAraeId.SelectedValue] has been configured
 					//and is associated with a company that exists in dynamics ax
 					SetSourceEndpointAndUser("SignFlow" );
 					//submit the request and retrieve the respons 
 					keys = client.create(recordWrapper);
 				}
 			}
 			catch (System.ServiceModel.FaultException <AifFault > aex)
 			{

 				//TODO add proper error handling
 				txtResult.Text += "AIF ERROR\\n" ;
 				txtResult.Text += "Message: " + aex.Message + "\\n" ;
 				txtResult.Text += "Source: " + aex.Source + "\\n" ;
 				txtResult.Text += "StackTrace: " + aex.StackTrace + "\\n" ;
 				txtResult.Text += "----------------------------------------\\n" ;
 				//txtResult.Text += aex.Detail.FaultMessageListArray[0].FaultMessageArray[0].Message;
 			}
 			catch (System.ServiceModel.FaultException fex)
 			{
 				//SOAP errors are handled here
 				//TODO add proper error handling
 				txtResult.Text += "Fault ERROR\\n" ;
 				txtResult.Text += "Message: " + fex.Message + "\\n" ;
 				txtResult.Text += "Source: " + fex.Source + "\\n" ;
 				txtResult.Text += "StackTrace: " + fex.StackTrace + "\\n" ;
 			}
 			catch (Exception ex)
 			{
 				//TODO add proper error handling
 				txtResult.Text += "ERROR\\n" ;
 				txtResult.Text += "Message: " + ex.Message + "\\n" ;
 				txtResult.Text += "Source: " + ex.Source + "\\n" ;
 				txtResult.Text += "StackTrace: " + ex.StackTrace + "\\n" ;
 			}
 			finally
 			{
 				//close the client
 				client.Close();
 			}

 			//----------------------------------
 			//Step 4 - Handle the response
 			//----------------------------------
 			//examine the respons - is it valid?
 			if (keys[0] != null ) // the repons contains info ->'s valid
 			{
 				txtResult.Text += "SUCCESS\\n" ;
 				KeyField [] fields = keys[0].KeyData;
 				foreach (KeyField field in fields)
 				{
 					//print the result
 					txtResult.Text += field.Field + ": " + field.Value + "\\n" ;
 				}
 			}
 		}

 		/// <summary>
 		/// Helper method - adds a SOAP Header defining the destination endpoint (local endpoint) in Dynamics AX
 		/// </summary>
 		/// <param name="nameOfEndpoint">The name of the local endpoint</param>
 		private void SetDestinationEndpoint(string nameOfEndpoint)
 		{
 				OperationContext .Current.OutgoingMessageHeaders.Add(MessageHeader .CreateHeader("DestinationEndpoint" , "http://schemas.microsoft.com/dynamics/2008/01/services" , nameOfEndpoint)); 
 		}

 		/// <summary>
 		/// Helper method - adds a SOAP Header defining the source endpoint name and the source endpoint user to use
 		/// </summary>
 		/// <param name="sourceEndpointName">the name of the source endpoint</param>
 		private void SetSourceEndpointAndUser(string sourceEndpointName)
 		{
 			string userName = HttpContext .Current.User.Identity.Name.ToString(); //returns the current user and domian - eg. egdk\\tomph
 			var addressHeader = AddressHeader .CreateAddressHeader("SourceEndpointUser" , "http://schemas.microsoft.com/dynamics/2008/01/services" , userName);
 			var addressBuilder = new EndpointAddressBuilder (
 			new EndpointAddress (new Uri ("urn:" + sourceEndpointName), addressHeader));
 			var endpointAddress = addressBuilder.ToEndpointAddress();
 			OperationContext .Current.OutgoingMessageHeaders.From = endpointAddress;
 		}

 	}

 }

Please remember that You have to use a bindign that support WS-Addressing. You can either use any of the pre defined ws bindings or use the “custom binding”. In my case I have used the custom binding, which is the most easy one to configure if You just want to test this out. Just set the Authentication property to NTLM instead of anonymous – we are not interested in anonymous user in AX.

Please keep in mind, that if Your setup allows it, You are always able to use the default endpoint, which means that all the SOAP header stuff can be left out of the equation.
Thanks to my collegue Michael Cronqvist for assisting me and also great thanks to my former collegue Tue Theilmann Jørgensen for pointing me in the SOAP Headers direction.

These aditional ressources might come in handy:

Posted in AIF, Microsoft Dynamics AX | Tagged: , , , , , , | Leave a Comment »

Connection troubleshooting

Posted by Torben M. Philippsen on November 22, 2011

One easy way to test your database connection is to use a udl file. Just create a new file and rename it to .udl. Open it and configure the connection using the connection properties:

Test_Database_connection

Test_Database_connection

Posted in Microsoft SQL Server | Tagged: , , | Leave a Comment »

SVC error when deploying AIF service to IIS

Posted by Torben M. Philippsen on November 21, 2011

If you are viewing an IIS error page like this after having published Your AIF service to IIS, the svc extension is probably missing in IIS:

missing_svc_mimetype

missing_svc_mimetype

This is probably caused by WCF not being correctly installed or registered in IIS.
To fix this do the following:

  1. Open a command prompt
  2. run the following command %windir%\Microsoft.net\framework\v3.0\WindowsCommunicationFoundation\servicemodelreg -i

If you are running a 64 bit OS, You will have to decide whether to run the above command from the “framework64″ folder og just the “framework” folder. The easy way to determine this, is to find out whether Your application pool for AIF is running in 32 bit mode. If not you can run the command for the 64 bit version  – otherwise You will have to use the 32 bit version.

To find out whether yourt application pool runs in 64 bit mode do the following:

AppPoolMode

AppPoolMode

  1. Go to the application pool section in IIS
  2. right click Your application pool – in this case the “MicrosoftDynamicsAXAif50″ pool and select advanced settings
  3. Search the property “Enable 32 bit applications”. A value equal to false means we are running in 64 bit mode and vice versa.

Posted in AIF, Microsoft Dynamics AX | Tagged: , , | 4 Comments »

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: