Calling managed code from Expression Web 4 HTMLJS Extensibility Add-Ins

A few folks have asked how to call managed code from the HTML\JavaScript extensibility layer within Expression Web 4.

Hope this helps!

John

1. Create a c# Class library project in Visual Studio, for this sample call it 'web'

2. mark the class as ComVisible

namespace web
{
    [ComVisible(true)]
    public class Class1
    {
    }
}

3. This will cause a compile time error, you will need to add the following using statement:
using System.Runtime.InteropServices;

4. Next implement Extensibility.IDTExtensibility2 in your class:

namespace web
{
    [ComVisible(true)]
    public class Class1 : Extensibility.IDTExtensibility2
    {
    }
}

5. This will cause a compile time error, you will need to add a reference to:
C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies\extensibility.dll
or for 32 bit machines
C:\Program Files\Common Files\microsoft shared\MSEnv\PublicAssemblies\extensibility.dll

6. You will still have a compile time error, you will need to stub out this interface:
     #region IDTExtensibility2 Members
    [ComVisible(true)]
    public class Class1 : Extensibility.IDTExtensibility2
    {
        public void OnAddInsUpdate(ref Array custom) {
            throw new NotImplementedException();
        }

        public void OnBeginShutdown(ref Array custom) {
            throw new NotImplementedException();
        }

        public void OnConnection(object Application, Extensibility.ext_ConnectMode ConnectMode, object AddInInst, ref Array custom){}

        public void OnDisconnection(Extensibility.ext_DisconnectMode RemoveMode, ref Array custom) {
            throw new NotImplementedException();
        }

        public void OnStartupComplete(ref Array custom) {
            throw new NotImplementedException();
        }
    }
    #endregion

7. At this point you should be able to build, the last thing you will want to do is create a method to call from your add-in, something like this should suffice for testing:
        #region JavaScript implementation
        public Class1(){} //CTor
        public String Version() { return "1.0"; } //Version info
        public String TestFunction() { return "MyTestFunction"; } //My test method to call
        #endregion

8. Next up is adding a JavaScript mapping in your manifest. A few bits of information will be needed

a. your DLL name on disk
b. your namespace
c. your class name

 

edit your manifest and a load element within the <addin> element, something like:

<addin>
<name>My</name>
<description>My</description>
<version>1.0</version>
<load type="web.Class1, web" name="utils" />
<panel id="My" title="My" src="my.html" />
</addin>

 

Looking at the load element in depth:

type="web.Class1, web"
web.class1, web == <namespace>.<classname>, <dll name on disk>

AND

name="utils"
utils is the namespace you wish to use in JavaScript to eventually call your methods (more later, but eventually we will call utils.TestFunction() from JavaScript).

9. Given you are following the code above you should create this manifest on disk as addin.xml, copy your web.dll right next to it.

10. create the html page, for this blog I use my.html, with the contents to follow, place it next to the addin.xml and your dll

<html>
<head></head>
<body onload="document.write(utils.TestFunction())">
</body>
</html>

 

11. copy all of your files (addin.xml, web.dll, my.html to a new directory call 'my' (or any name you prefer) in
%appdata%\Microsoft\Expression\Web 4\Addins

12. Run Web 4

13. Under the panels meny you should see My, click that and you will see the return value from
public String TestFunction() { return "MyTestFunction"; }
placed into your document, in this case "MyTestFunction".

There are many usages that come to mind when looking at this functionality, passing a file location of a JPG and resizing it in managed code and then returning the URI or file path back to javascript is one example.

Hope you guys find this useful, if you have any problems I wanted to call out a few common issues I have seen people fall into
1. Make sure your class is public
2. make sure your methods are public

Enjoy!