Philippsen's Blog

Everyday findings in my world of .net and related stuff

Archive for the ‘Enterprise Portal Development’ Category

Unable to render content due to an error. Please contact your system administrator.

Posted by Torben M. Philippsen on May 23, 2016

Recently I experienced a strange error in an usercontrol. The error would cause the classic “Unable to render content due to an error. Please contact your system administrator.” message on EP and in the eventviewer I saw this:

EV1

EV2

EV3

The strange thjing turned out to be that the code for the usercontrol was an exact match with the one from a reference environment where everything worked just fine.

Trying to narrow things down I ended up finding that it was the AllowPaging property on the grid that was set to false that caused the error. Setting this property to true, would make the control work just fine. However my customer didn’t want paging – and it woked just fine in the reference environment. Giving this thought I concluded that the error was related to data. In my environment the dataset would return 55 records and in the reference environment I would have just 12 records. I started to play around with the PageSize property of the grid and found the the magic limit was 45 records. A limit of 44 in the PageSize property would make the control work just fine, whereas a limit of 45 would make the control crash with the above eventlog entries to follow.

I don’t think that the error is related to 45 records but more likely the size of the entire dataset. In my case the dataset contains information about expences and in that context some image/binary bitmap data. I therefore expect the data to be quite big.

 

Conclusion:

If you begin to experience strange errors like the ones above – maybe it would be a good idea to look into the size of data.

Posted in Enterprise Portal Development, Microsoft Dynamics AX | Tagged: , | Comments Off on Unable to render content due to an error. Please contact your system administrator.

Troubleshooting Enterprise Portal error messages

Posted by Torben M. Philippsen on April 4, 2016

If you have been working with enterprise portal development, you will probably have gone through the same levels of frustration as I because error messages are not good in adding usable information into these messages. Over time I have collected some sites with suggestions on how to troubleshoot these more or less cryptric messages.

Error: Enterprise Portal Web Parts show "Unable to render content" error
https://blogs.msdn.microsoft.com/emeadaxsupport/2010/09/23/enterprise-portal-web-parts-show-unable-to-render-content-error/

Error: Unable to render content due to an error. Please contact your system administrator.
https://blogs.msdn.microsoft.com/emeadaxsupport/2010/11/17/how-to-troubleshoot-enterprise-portal-error-unable-to-render-content-due-to-an-error-please-contact-your-system-administrator/

Generel troubleshooting: https://msdn.microsoft.com/en-us/library/cc554278.aspx

Posted in Enterprise Portal Development, Microsoft Dynamics AX | Tagged: , , , , | Comments Off on Troubleshooting Enterprise Portal error messages

Record won’t update from EP–it almost seems like the dataset has been disconnected from AX

Posted by Torben M. Philippsen on February 3, 2015

In a recent customer project I had to fix an error where a certain record seemed to be updated on EP but not in AX.

The scenario:

In an expense module one would have the ability to upload expenses/receipts. For each expence you would be able to add expense lines.
In this case when uploading an expence and returning and trying to add expence lines in an AX bound grid – the grid would update just fine, but when looking in AX, the record wouldn’t have updated.

I spent the first couple of days trying to figure out a way to force EP to update the record in Ax without any luck – and I was really trying everything and everyway like described here.
I almost by accident discovered that having uploaded a new receipt and trying to update the record from EP – it was also not possible to update the record from within AX – ax just hang. This was somekind of breakthrough since I now had an idea of the record being locked. I started to take interest in the database and analyzing locks:

select * from sys.tables where OBJECT_id in
(select distinct rsc_objid from sys.syslockinfo)
   

Navigating my flow on EP, I realized that a lock would be created in the EPSTATESTORE table and this lock wouldn’t disappear by itself as it should. The big question was now when this lock would be created. It took some time narrowing down where the lock would be created and wich of my webparts actually caused it but finally I was certain to have found the right webpart. Analyzing the code gave me absolutely no clue ablut where the lock could be created –everything seemed just fine. Once again I had to take drastic measures and started to tear down the webpart commenting one method at a time trying to identify which method would cause the lock. As You can imagine this was pretty time consuming but I was certain that finding and removing the cause of the lock would solve almost every problem we had.

Finally i found that a call to a static method of the dataset in AX would cause the lock and lloking into that method in AX It was obvious that an inbalance in ttsbegin and tts commit caused the lock. Ttsbegin was places outside an if statement where the ttscommit was placed inside the if statement. 

The great point of this article is that next time when I experience something not working from EP that should be working I will start looking at possible locks a bit sooner as i did facing this problem.

A link to two other sql scripts that I used can be found here

Posted in Enterprise Portal Development | Tagged: , | Comments Off on Record won’t update from EP–it almost seems like the dataset has been disconnected from AX

Display image from AX as embedded object in usercontrol

Posted by Torben M. Philippsen on January 9, 2015

Example of usercontrol markup:

<%@ Control Language=”C#” AutoEventWireup=”true” CodeFile=”DIVendInvoiceImage.ascx.cs” Inherits=”DIVendInvoiceImage” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.Portal, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts” TagPrefix=”dynamics” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.Portal, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.Portal.UI.WebControls” TagPrefix=”dynamics” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.Data.Ax, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.Data.Ax” TagPrefix=”dynamics” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.Metadata.Ax, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.Metadata.Ax” TagPrefix=”dynamics” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.BusinessConnector, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.BusinessConnector” TagPrefix=”dynamics” %>

<%@ Register Assembly=”Microsoft.Dynamics.Framework.BusinessConnector.Proxy, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.BusinessConnector.Proxy” TagPrefix=”dynamics” %>   

<%@ Register Assembly=”Microsoft.Dynamics.Framework.Portal, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

    Namespace=”Microsoft.Dynamics.Framework.Portal.UI.WebControls.Workflow” TagPrefix=”dynamics” %>    

 

 <dynamics:AxDataSource ID=”DS_VendInvoiceImage” runat=”server”

    DataSetName=”DIVendInvoiceImage” ProviderView=”LedgerJournalTrans” />

 

<dynamics:AxMultiSection

    ID=”AxMultiSection1″ runat=”server”>

<dynamics:AxSection ID=”AxSection_Image” runat=”server” Caption=”Faktura”

        Expanded=”True” >

    <%=showImage() %> 

</dynamics:AxSection>

</dynamics:AxMultiSection>

Usercontrol codebehind

using System;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Globalization;

using Microsoft.Dynamics.Framework.Portal;

using Microsoft.Dynamics.Framework.Portal.UI.WebControls;

using Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts;

using Microsoft.Dynamics.Framework.Portal.UI.WebControls.Workflow;

using Microsoft.Dynamics.Framework.Portal.UI;

using Microsoft.Dynamics.Framework.Data.Ax;

using Microsoft.Dynamics.Framework.Metadata.Ax;

using Microsoft.Dynamics.Framework.BusinessConnector;

using Proxy = Microsoft.Dynamics.Framework.BusinessConnector.Proxy;

using ApplicationProxy = Microsoft.Dynamics.Portal.Application.Proxy;

using Microsoft.Dynamics.Framework.BusinessConnector.Session;

using Microsoft.Dynamics.Framework.BusinessConnector.Adapter;

using System.Collections.Generic;

using System.Diagnostics;

 

public partial class DIVendInvoiceImage : System.Web.UI.UserControl

{

    string imageHtml;

 

    protected string showImage()

    {

        return imageHtml;    

    }

    protected void Page_Load(object sender, EventArgs e)

    {

        AxBaseWebPart.GetWebpart(this).ExternalContextChanged += new EventHandler<AxExternalContextChangedEventArgs>(ExternalContextChanged);

       

    }

 

    void ExternalContextChanged(object sender, AxExternalContextChangedEventArgs e)

    {

        IAxaptaRecordAdapter currentRecord = AxBaseWebPart.GetWebpart(this).ExternalRecord;

        if (currentRecord != null)

        {

            imageHtml = (string)this.DS_VendInvoiceImage.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call(“showImage”, (Int64)currentRecord.GetField(“RecId”), Convert.ToString(AxBaseWebPart.GetWebpart(this).Width), Convert.ToString(AxBaseWebPart.GetWebpart(this).Height));

 

        }

    }

 

}

 

ShowImage method on dataset (x++ code) – pushing differenet kinds of object tags

//Called from ASP.NET

str showImage(RecId _ledgerJournalTransRecId, str _widthZone = ‘450px’, str _heightZone = ‘600px’)
{
#Web
NAX_ScanImageTable      NAX_ScanImageTable;
str                     ret;
str                     url;
LedgerJournalTrans      ledgerJournalTransLocal = LedgerJournalTrans::findRecId(_ledgerJournalTransRecId, false);
EPWebsiteParameters     EPWebsiteParameters;
;

    _widthZone = ‘470px’; // tec, cts, 2011.01.20, Defect 229,335  width changed from 250px to 350px
_heightZone = ‘450px’;

    ret = ‘<P style=”TEXT-ALIGN: center”>’+’@VIA98’+'</p>’;
NAX_ScanImageTable = NAX_ScanImageTable::find(ledgerJournalTransLocal.naxImageId);
if (NAX_ScanImageTable.ScanImage)
{
select firstOnly EPWebsiteParameters;
url = EPWebsiteParameters.ExternalUrl+’/’+#resourcesRelDir+’/diimageaction.aspx?’;
url +=’table=’+int2str(NAX_ScanImageTable.tableId);
url +=’&field=’+int2str(fieldnum(NAX_ScanImageTable,ScanImage));
url +=’&recid=’+int642str(NAX_ScanImageTable.RecId);
//EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>
url += ‘&fileType=’+NAX_ScanImageTable.ImageFormat;
//EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–
//EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>
//do something to handle pdf file extension
if (NAX_ScanImageTable.ImageFormat == ‘pdf’)
{
ret = strfmt(‘http://%2‘, url, url);
}
else
{
//if not pdf do as usual – handle as tiff
//EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–
ret = strfmt(‘http://%2‘, url, url);

          //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>
}
//EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–
}
else if(NAX_ScanImageTable.Text)
{
ret = ‘<DIV id=”bsplustxt”>’+NAX_ScanImageTable.Text+'</DIV>’;
}
return ret;
}

diimageCaption.aspx markup and code – setting the content type according to the memorystream content:

<%@ Page Language=”C#” Trace=”false” %>

<%@ Assembly Name=”Microsoft.Dynamics.BusinessConnectorNet, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null” %>

<%@ Assembly Name=”Microsoft.Dynamics.Framework.Portal, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null” %>

<%@ Assembly Name=”Microsoft.Dynamics.Framework.BusinessConnector, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null” %>

<%@ Assembly Name=”Microsoft.Dynamics.Framework.BusinessConnector.Proxy, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null” %>

<%@ Import Namespace=”Microsoft.Dynamics.BusinessConnectorNet” %>

<%@ Import Namespace=”Microsoft.Dynamics.Framework.Portal” %>

<%@ Import Namespace=”Microsoft.Dynamics.Framework.BusinessConnector.Proxy” %>

<%@ Import Namespace=”Microsoft.Dynamics.Framework.BusinessConnector.Session” %>

<%@ Import Namespace=”Microsoft.Dynamics.Framework.BusinessConnector.Adapter” %>

 

<script runat=”server”>

    void Page_Load(object sender, EventArgs e)

    {

        string table = this.Request.QueryString[“table”];

        string field = this.Request.QueryString[“field”];

        string recid = this.Request.QueryString[“recid”];

        //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>

        string fileType = this.Request.QueryString[“fileType”];

        //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–       

        if (recid != null && recid != String.Empty)

        {

            AxSharepointWebSession session = null;

            try

            {

                table = table == null ? String.Empty : table;

                field = field == null ? String.Empty : field;

 

                session = SessionHelper.Instance.GetSharepointSession();

 

                if (session != null)

                {

                    session.InitWeb(HttpContext.Current, Page.IsPostBack);

                    string base64 = (string)session.AxaptaAdapter.CallStaticClassMethod(“Webapplication”, “GetImage”,

                                    int.Parse(table), int.Parse(field), long.Parse(recid));

                    

                    byte[] bytes = Convert.FromBase64String(base64);                   

                    if (bytes != null && bytes.GetLength(0)>0)

                    {

                        //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>

                        string contentType;

                        if (fileType.Equals(“pdf”))

                        {

                            contentType = “application/pdf”;

                        }

                        else

                        {

                            //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–

                            contentType = “image/tiff”;

                            //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso –>                           

                        }

                        //EG/2015.01.07/EGTOP, 00414358 Integration til Picasso <–

                        this.Response.ContentType = contentType;

                        this.Response.BinaryWrite(bytes);

                    }

                }

            }

            catch (System.Exception E)

            {

                System.Diagnostics.EventLog.WriteEntry(“EP”, string.Format(“Error {0}”, E.Message),System.Diagnostics.EventLogEntryType.Error, 3);

           

            }

            finally

            {

                if (session != null)

                {

                      SessionHelper.Instance.ReleaseSharepointSession(session);

                }

            }

        }

    }   

</script>

Posted in Enterprise Portal Development | Tagged: , , , | Comments Off on Display image from AX as embedded object in usercontrol

Multiselection checkboxes in an AxGridview

Posted by Torben M. Philippsen on October 30, 2014

For a customer Ihad to fix a very non user friendly behavier in an AxGridview control.

The scenario was that they had an AxGridview control containing attachments in an expence module. For a single Expence you would one or more attachments – those attachments would be shown in the AxGridview when viewin the given expence post. In the gridview you would be able to select and deselect attachments but in the standard behavior the user flow would be something like this:

  1. Mark a row in the gridview – wait for postback to finish
  2. now the row is in edit mode – check the combobox – wait for postback
  3. click the update command button in the row – wait for poatback to finish

That’s a lot of waiting and posting back just to check a combobox. Ofcourse the customer wanted a more smooth solution.

My workaround was to try and create comboboxes that would be checkable but without posting back all the time. Doing this I had to consider how I would read the checked state from the comboboxes and persist the state to Ax/the underlying dataset. Here’s what I ended up with…

The markup

In order to have a combobox that is checkable at all times – not just in editmode, you will have to create a template field
EP_Multiselect_markup
Please notice that the AxGridview doesn’t allow paging and editing. Also you should notice that the combox doesn’t postback.

The first time the page loads checkboxes should be checked according to values from AX. Notice that the checked propety is handled by the Marked method

private Hashtable checkbox_values = new Hashtable();

    /// <summary>

    /// Method used in when each row is databound (See markup)

    /// </summary>

    /// <param name="dataItem"></param>

    /// <param name="container"></param>

    /// <returns></returns>

    protected bool Marked(object dataItem, object container)

    {

        AxGridViewRow gridViewRow = (AxGridViewRow)container;

        //CheckBox checkbox = (CheckBox)gridViewRow.FindControl("markCheckbox");

        DataSetViewRow row = dataItem as DataSetViewRow;

        if (row != null)

        {

            //string hashcode = checkbox.UniqueID;

            string hashcode = gridViewRow.RowIndex.ToString();

            if (this.checkbox_values.ContainsKey(hashcode))

            {

                //return row.Mark((bool)this.checkbox_values[hashcode]);

                return (bool)checkbox_values[hashcode];

            }           

        }

        return false;

    }

You will notice that the checked state depends on whether the current rows combobox has been added to a hashtable. The hashtable contains a boolean value for each rows combobox indicating whether it should be checked or not. The hashtable is populated on every postback like this:

 

   protected void Page_Load(object sender, EventArgs e)

    {

        getChecked(false);

 

 

//EG/2014.10.28/tomph, 00392460 XpenseAttachments –>

    /// <summary>

    /// Method used to fetch all marked checkboxes from the grid.

    /// This approach is used because we use a classic .net combobox with no postback (not an axboundfield)

    /// </summary>

    /// <param name="_saveToDataset">indicates whether this method is triggered from the save button click event or is just a normal postback</param>

    protected void getChecked(bool _saveToDataset)

    {

        foreach (GridViewRow row in AxGridView1.Rows)

        {

            if (row.RowType == DataControlRowType.DataRow)

            {

                CheckBox chk = (CheckBox)row.FindControl("markCheckbox");

                string hashcode = row.RowIndex.ToString();

                    if (chk.Checked)

                    {

                        if (!checkbox_values.ContainsKey(hashcode))

                        {

                            //only add if it does not exist

                            checkbox_values.Add(hashcode, true);

                        }

                        else

                        {

                            //update value if exists

                            checkbox_values[hashcode] = false;

                        }

                        if (_saveToDataset)

                        {      

                               //save the checked state to the datasat

                               DataSetView dsv = this.ImageDS.GetDataSourceView(this.AxGridView1.DataMember).DataSetView;

                               dsv.SetCurrent(row.RowIndex);

                               DataSetViewRow dsvr = dsv.GetCurrent();

                               dsvr.BeginEdit();

                               dsvr.SetFieldValue("selection**", 1);

                               dsvr.EndEdit();

                               this.AxGridView1.UpdateRow(row.RowIndex, false);

                        }

                    }

                    else

                    {

                        if (!checkbox_values.ContainsKey(hashcode))

                        {

                            //only add if it does not exist

                            checkbox_values.Add(hashcode, false);

                        }

                        else

                        {

                            //update value if exists

                            checkbox_values[hashcode] = false;

                        }

                        if (_saveToDataset)

                        {

                            //save the unchecked state to the datasat

                            DataSetView dsv = this.ImageDS.GetDataSourceView(this.AxGridView1.DataMember).DataSetView;

                            dsv.SetCurrent(row.RowIndex);

                            DataSetViewRow dsvr = dsv.GetCurrent();

                            dsvr.BeginEdit();

                            dsvr.SetFieldValue("selection**", 0);

                            dsvr.EndEdit();

                            this.AxGridView1.UpdateRow(row.RowIndex, false);

                        }

                    }               

            }

        }

    }

The only thing we will have to do know is to persist the checked comboboxes to the data, when clicking a “save/update” button. The save button click event calls the same method as above. Only difference is that the boolean value true is passed which again causes each row to be updated.

    protected void UpdateButton_Click(object sender, EventArgs e)

    {

        getChecked(true);

        this.ImageDS.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call("updateSelections");

    }

Posted in Enterprise Portal Development | Tagged: , , , | Comments Off on Multiselection checkboxes in an AxGridview

Handling timeout issues on the EnterPrise Portal

Posted by Torben M. Philippsen on October 29, 2014

Lately I have been struggling with a timeout issue for a customer on the Enterprise Portal for Dynamics AX 2009.

I ended up doing two things – here are my experiences:

The problem:

If You have been working with EP, You have probably seen something like this on occasion
EP_TimeOut

The solution:

I will not claim to have a bulletproof solution but there are things that You might want to try

  1. In the AX client navigate to administration—>setup—>internet—>Enterprise Portal—>Parameters
    EP_parameters
    You could try to increase the values for timeout and history and see how that plays out for you.
  2. Another approach could be to increase the session timeout for the AX website in IIS. In order to do that you will have to do two things…
    Find the web.config file for your ax site. The path may look something similar to this C:\inetpub\wwwroot\wss\VirtualDirectories\80 – but ofcourse this may vary depending on your installation structure.
    In the configsections (in the top section of the web.config) you will have to add

    <sectionGroup name="Microsoft.Dynamics">
          <section name="Session" type="System.Configuration.SingleTagSectionHandler, System, Version=1.0.5000.0, Culture=neutral,PublicKeyToken=b77a5c561934e089" />
    </sectionGroup>

    EP_webConfig1
    Now scroll down and place the pointer after <system.web/> and before <runtime> and add

    <Microsoft.Dynamics>
        <Session Timeout="120" />
    </Microsoft.Dynamics>

    EP_webConfig2
    The session timeout is set in seconds and according to your needs.

    Good luck…

 

 

Thanks to my collegue Martin Lindhoff Lysgaard for input and assistance.

Posted in Enterprise Portal Development | Tagged: , , | Comments Off on Handling timeout issues on the EnterPrise Portal

How to debug x++ code from Enterprise Portal

Posted by Torben M. Philippsen on December 16, 2013

This article is mainly to support my own memory on how to configure things and being able to debug x++ code when executed from Enterprise portal (EP).

In order to being able to debug x++ executed from EP you need to follow these few steps:

  1. Log on to the server runnning the AOS
  2. Open the Microsoft Dynamics AX Server Configuration utility. To open Start –> Control Panel –> Administrative Tools –> Microsoft Dynamics AX 2009 Server Configuration.
  3. If you are not allowed to alter the existing configuration, create a new one that supports debugging.
    Click Manage then Create configuration. Give a name to the new configuration in the Create Configuration window then click OK

    On the Application Object Server tab, select Enable breakpoints to debug code X++ code running on this server. Click on Apply button.
    ServerConfiguration

  4. Click on the OK button to close the configuration window. You will get a message that indicates AOS is going to be restarted.’>Click on OK button to close the configuration window. You will get a message that indicates AOS is going to be restarted.
  5. Actually the debugger works on the server where IIS is running and Enterprise Portal is hosted. I used a single system and all the things are on the same system. If you are accessing a system remotely using Terminal Services then from the Start menu click Run. Type mstsc /consolein the Open text box and click OK
    This opens a console session in Terminal Services. Console session is required to debug Ax EP
  6. Open the Services window for the system. To open it Start –> Control Panel –> Administrative Tools –> Services.
    Right-click the World Wide Web Publishing Service and click Properties.
    Click the Log On tab
    Select Allow service to interact with desktop as shown below
    ServicesProperties
  7. Open the web.config file located in :\Inetpub\wwwroot\wss\VirtualDirectories\\, here the port number of the Enterprise Portal site. If you forgot the port then there is a way to check it out. Open Ax client then Administration main menu –> Setup –> Internet –> Enterprise Portal –> Web sites, here you can see the port
  8. Locate out the compilation element then set the debug attribute to true.
    Save the changes.
    Reset IIS (shouldn’t be necessary but I always do this just to make sure)
  9. Open the Microsoft Dynamics AX Configuration utility. To open it Start –> Control Panel –> Administrative Tools –> Microsoft Dynamics AX 2009 Configuration
  10. Set the Application Object Server Instance drop-down menu to Business Connector (non-interactive use only).
  11. If you are not allowed to alter the existing configuration, create a new one that supports debugging.
    Click on Manage button then click Create configuration. In the Create Configuration window, name the new configuration then click OK button.
    On the Developer tab, select Enable user breakpoints to debug code in the Business Connector and Enable global breakpoints to debug code running in the Business Connector or client then click on Apply button
  12. Click on OK button to close the configuration window
  13. Open the Microsoft Dynamics AX client
    On the Tools menu, click Options to display the Options window.
    On the Development tab, select When Breakpoint from the Debug mode list box, and then click Apply. This enables debugging mode on the client
    OptionsMenu
  14. Close the options window.
  15. Set the breakpoint of your choice in the x++ code
  16. Open the Debugger window manually. To open debugger manually click on Tools > Development Tools > Debugger
  17. Now execute the web form where the method has been invoked. It should work now and You should hit you breakpoint – nice:-)

Posted in Enterprise Portal Development | Tagged: , , | Comments Off on How to debug x++ code from Enterprise Portal

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 Portal Development, Microsoft Dynamics AX | Tagged: , , | 2 Comments »

Viewin a list of applied webparts on a EP page

Posted by Torben M. Philippsen on June 8, 2011

If You find yourself struggling with clientside events a list of applied WebParts could come in handy. You can view a list of applied webparts as well as the order in which they are applied to the content  page by appending “&contents=1” to the querystring. If you do so, You will see something like this:

EP WebPart list

Posted in Enterprise Portal Development | Tagged: | Comments Off on Viewin a list of applied webparts on a EP page

Enterprise Development – ressources

Posted by Torben M. Philippsen on February 1, 2011

In my search for relvant ressources related to Enterpise Portal development I found that it’s an area that seems to lack a lot of fundamental information. For instance it’s at the moment not possible to find any books describing the subject.

Therefore i figured that I would use this blog to collect some of the internet ressources that I find useful – please see links below:

Posted in Enterprise Portal Development | Comments Off on Enterprise Development – ressources

 
%d bloggers like this: