AX – Object ‘CLRObject’ could not be created

This error had me a little worried for a few days. “Object ‘CLRObject’ could not be created” and “Request for the permission of type ‘InteropPermission’ failed.”
 
I was trying to create a .NET class (to do some irrelevant stuff) and run that object from Dynamics AX 2009.  My training and docs said it should be possible.  Sweet!  However, I just kept hitting brick walls.  Eventually, I figured out all of the secret hand-shakes and thought it would be good to put them somewhere on the web to save some other programmer a week of research.
 
1. Create the .net class using primitive types that you KNOW will be compatible with AX and X++.  There are probably ways around this, but you are better off starting simple and adding complexity AFTER you get the simple stuff working.  The assembly needs to be Signed (strong-name) and it should be installed into the GAC of the AX Object Server (AOS). Make sure that you choose a good name for your assembly so you can find it in the GAC.
 
2. Once your dll is in the GAC, log onto the AOS server (via console or RDP), open the AX client, open the AOT (AX object tree) and add a new reference.  Pick the assembly from the GAC (avoid using the local file system).
 
3. Create a X++ class to wrap your DLL.  Create functions in your AX class to wrap your .NET function calls.  Those AX (wrapper) functions must be public static server.  Within each function, you need to ask for InteropPermission before instantiating your classes.
Example:
 
public static server int TestOne(int int1, int int2)
{
   AxClrTest.One TestOne;
   int re;
   ;
 
   //ask for permission to use a CLR object [AX 4.0]
   new InteropPermission( InteropKind::ClrInterop ).assert();
 
   //then create the CLR object
   TestOne = new AxClrTest.One();
 
  //call the CLR function
  re = TestOne.Add(int1, int2);
 
  return re;
}
 
Now that the wrapper class is ready, you can successfully call the objects in your .NET file by calling your (wrapper) class.
 
Example (I will call this function from the insert event handler for some table, such as CustTable):
 
public void insert()
{
  int re;
  AxClrTest.One TestOne;
  ;
  super();
 
  //calling CLR via a static, server-side class
  re = AxClrTestWrapper::TestOne(this.Int1, this.Int2);
  info(strfmt(“1) TestOne.Add(%1, %2) = %3”, this.Int1, this.Int2, re));
 
/*
  //Important fun fact: The above code works, and the below code fails!
  //Creating a CLR object here would fail, because this code would try to run client-side
  //You would have to GAC your dll on every AX client.  Forget that.  Run it on the server.
  TestOne = new AxClrTest.One();
  re = TestOne.Add(this.Int1, this.Int2);
  info(strfmt(“2) TestOne.Add(%1, %2) = %3”, this.Int1, this.Int2, re));
*/
}
 
Consider the security caveats that would go along with allowing AX to run some arbitrary (or non-arbitrary) code client-side.  Microsoft is clearly trying to prevent the opportunity for running malicious code via AX and murdering every machine on your work domain.  (think about it for a moment, you’ll recognized the danger pretty quickly).
 
So, the server-side approach is the only way.  [puts on my critic hat] It wouldn’t kill Microsoft to automatically build an X++ wrapper for the CLR functions when the DLL reference is initially created/imported in the AOT.  In fact, it would be good to have a chance to bind those wrapper functions to AX roles.  Yes, I know I am dreaming. [takes off critic hat]
 
Keep in mind that you will not have much luck writing/editing/changing this code from an AX Client session unless it is running on the server.  Think about it.  Your .NET assembly is GAC’d on the server, not the client.  So, by writing a class to wrap it, you put it on the server (once).  From now on, you can do your coding in the client as long as you refer to the wrapper class.
 
Also, I will do a few more experiments this week and see how far I can push the edge of this technology.  I’ll update this blog post when I find out.
 
Follow up: I have found a few other ways that will work, but none of them work-out to be as convenient as this approach.  However, I did learn a much better way of handling errors in AX/CLR.  You might find that blog post helpful.
 
Advertisements

About Tim Golisch

I'm a geek. I do geeky things.
This entry was posted in .net, Dynamics AX, Errors. Bookmark the permalink.

5 Responses to AX – Object ‘CLRObject’ could not be created

  1. Ashok M Kumar says:

    I am having a Dll which calls a Webservice internally. If i remove the line which calls the webservice, there is no problem in calling the .net DLL, but if i call the Webservice i am getting error. What do i need to do for this. Please help.

    • Tim Golisch says:

      My friend, Corey Lasley, set up our AX to call a web service directly (not through a DLL). That seemed to work nicely, so all of our web service calls happen directly from AX, not via a .NET DLL. If you prefer to make the call in the DLL, then I have a few questions for you:
      1) in AX, have you set up your DLL call in a error handler like I discuss in my June 29 posting? It really helps narrow-down where the error is happening.
      2) when you say that you comment-out the web service call, it sounds like you are doing that in the .net code.
      (2a) If this is true, I would write a quick test-jig in .net to call the dll (with web service) just to make sure the dll is working nicely, by itself.
      (2a1) if it works via the test jig, then I would look into implementing some of the CAS hooks to have .net ask for better permissions.
      (2ab) if it doesn’t work via the test jig, I would add lots of error handling to the code in the .dll to log errors to the HDD and get better insight into what is going on in the DLL.
      (2b) if it only works if you comment-out your x++ code, then my guess is that the problem is with the interface to your .net function. Remember that it will ONLY work if you have a very primitive interface (primitive variables {int, string, float}, no overloading, no optional args, no nullable or generics).
      Good luck Ashok. Let me know how it turns-out.

  2. Arun joseph says:

    When i run the batch job its show some error:
    Request for the permission of type ‘InteropPermission’ failed.
    (s)classes\Interpermission\demand
    (s)classes\CLRObject\new
    (s)classes\oocbankrecomovefiles\removezerochar – line 3
    (s)classes\oocbankrecomovefiles\fetchfiles – lines 22

    please help me..

    • Tim Golisch says:

      Since I have no idea about any of your code, I can only give you some advice: 1) I have 3 posts about this topic. Reading all three might help you. It helped me. Which is why I wrote all three posts. 2) Isolate the problem: make a test jig in .net to test your CLR object to make sure it is working correctly. 3) If this is a new class (never worked in AX up to now), try to simplify it until it works, then add features. It is much easier to get a working CLRObject to do more stuff than it is to get AX to accept any CLR object, ever. 4) If you get this error after you made some changes to a working CLRobject, try recompiling your AOT, or wrapper classes. 5) stackoverflow.com has many helpful users who are glad to help troubleshoot your code, as long as you post code and promptly answer their questions about your code.

  3. Dileep says:

    Thanks A lot man, Your code helped a lot,
    Keep on Posting….

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s