Easily create an Add-in for Expression Web 4 with the Add-in Builder


With today’s launch of Expression Web 4, we’ve made extending Expression Web’s functionality easier than ever.  Developers can create Add-ins for Expression Web by using HTML, JavaScript and CSS standards they already know!  We have also simplified integrating your Add-ins into Expression Web’s Panel and menu system using XML.  In order to make it even easier, we are providing an Add-in on the Expression Community site that makes it super simple to build other Add-ins. It’s a classic Chicken or the Egg problem solved with the “Add-in Builder”. Click here to download the Add-in Builder. Once you have downloaded it, you can install it within Expression Web 4 directly via the Tools -> Add-ins menu! Click the Install button and choose the .xadd file you just downloaded.

Before we get started building an Add-in with the Add-in Builder let’s take a look at the exact XML used in order to integrate the Add-in Builder itself into Expression Web 4.  It’s pretty simple and very straightforward.

<addin legacy=“yes” developer=“yes”>

<name>Add-in Builder</name>

<load type=“AddinUtilities.Utilities, AddinUtilities” name=“addinUtils”/>

<description>Chicken or the Egg?</description>

<command id=“AddinBuilderCommand”

           onclick=“xweb.application.showModalDialog(‘AddinBuilderTestPage.html’,

           ‘Add-in Builder’,’dialogHeight:500;dialogWidth:700;resize:yes’)”>

         <menuitem parent=“MENU_Tools” before=“MENU_Tools_AddIns” label=“Add-in Builder…”/>

</command>

</addin>

As simple as it is, learning and authoring new XML syntax can be time consuming and is largely based on trial-and-error. The Add-in builder provides a user-friendly interface that makes it simple to generate the XML and all the associated content files. In addition, the add-in you define is created in the correct location and a site is created for you inside of Expression Web 4 for you.  Why is that cool? Simple, once your add-in is generated you can live edit it just like any other site!

We’ve cleared all of the hurdles for you and now as a Web Developer you can focus on building the HTML, CSS and JavaScript inside of an Expression Web panel or dialog to build powerful new functionality instead of how to integrate your ideas into Expression Web itself.

1. If you haven’t downloaded the Add-in already you can download the Add-in Builder from here. Install the .xadd file in Expression Web 4 via the Tools -> Add-ins menu. Click the Install button and choose the .xadd file you just downloaded.

2.Once you have installed the Add-in Builder add-in you can access it in Expression Web 4 via Tools > Add-in Builder.

3.The first step is to describe your add-in, including name, description, homepage, and version. (I’ll publish another post in the near future to describe the other more advanced options in this dialog.)

 

4. To create a panel for your add-in, click Add Panel. Name, Source, and ID are required fields.

 

5. Click Insert, and then click Create Add-in. That’s it; it’s that easy to create your own Add-ins.

After the Add-in is created,  a new site appears in Expression Web 4, with your Addin.xml file and an empty html file (the content of the panel you just defined!).

 

At this point, restart Expression Web 4. Upon restarting, the Add-in panel (or, if you selected, a dialog or assembly) will automatically be installed and available for use.

7. If you created an Add-in panel, go to the Panels menu and click the name you gave for your panel.

 

A panel hosting the empty html page opens.

 

The panel can be docked, moved, pinned, etc… within the Expression Web 4 application just like any other default panel!

8.Open panel.html from the site Expression Web created for your Add-in. Add <h1>Hello World</h1> to the page and save it.

9.Right click inside your open “My First Panel” tab and choose Refresh. You should be able to immediately see the HTML you added rendered in your panel!

Marc Kapke, Software Development Engineer in Test

Comments (20)

  1. ZippyV says:

    Addons in .net would be much more useful.

  2. Marc_K says:

    @ZippyV Building Add-ins in .NET has been available in most releases of Expression Web and is still available in version 4.

    You can build them almost exactly the same way you build an Office Add-in.

  3. Marc_K says:

    @ZippyV

    We just uploaded the Visual Studio template to build Managed Add-ins to the community gallery.

    gallery.expression.microsoft.com/…/xWeb4SDK

    If you are interested in building managed add-ins the above template will make getting started much easier.

  4. steve says:

    Is there a comprehensive example available – like something that would inject a jqueryui component into a site? At a minimum something that requires injecting a set of a of html,css and javascript? or some combination thereof?

  5. krr says:

    How to you add an item to the code view contextmenu?

  6. Garry Trinder says:

    Hi krr,

    The current extensibility model does not support editing the context menu. Just curious…what would you like to change in the context menu?

    Anna

  7. Garry Trinder says:

    Steve, have you seen our blog post on the Bing Map plug-in?

    blogs.msdn.com/…/create-useful-professional-looking-extensions-to-expression-web.aspx

  8. krr says:

    Anna,

    I created an addin that adds menu items to the format menu to make the current selection Titlecase, Uppercase, or Lowercase. I would like to add the commands to the context menu in both the Design and Code mode.

    -Krr

  9. Krr says:

    Anna,

    How do you access a dll for use within a JavaScript file?

    Let's say I have a WebHelper.dll that is a class library that contains a single class “Utilities” with the function ToTitleCase().

    I have the following line in the manifest:

    <load type="WebHelper.Utilities, WebHelper" name="WebHelper" />

    In the javascript file I have the following:

    xweb.document.selection.text = WebHelper.ToTitleCase(xweb.document.selection.text);

    It doesn’t work. Any suggestions?

    Thanks,

    -Krr

  10. JD_MSFT says:

    Couple things you will need to do to your DLL

    1. class and methods to be called both need to be public

    2. add a proj reference to

    C:Program Files (x86)Common Filesmicrosoft sharedMSEnvPublicAssembliesextensibility.dll

    or on 32 bit systems

    C:Program FilesCommon Filesmicrosoft sharedMSEnvPublicAssembliesextensibility.dll

    3. add: using System.Runtime.InteropServices;

    4. add [ComVisible(true)] above your class declaration

    5.implement (stub) the Extensibility.IDTExtensibility2 interface in your class ala:

    public class Program : Extensibility.IDTExtensibility2

    6. add stubs for the interface (see below), replace the constructor with your class name (or you will not compile)

    7. recompile, replace DLL, restart xweb

    Here are the stubs to add to your class, will try to get a blog post out soon with better examples!

    #region IDTExtensibility2 Members

           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

           #region JavaScript implementation

           public Program()

           {

           }

           public String Version()

           {

               return "1.0";

           }

           #endregion

  11. krr says:

    jdixon,

    I'm receiving the following in the error log:

    Info: Line 5 column 1 error 'ToTitleCase()' 'Object doesn't support this property or method'

    I think maybe I'm having a problem with the manifest.

    Here's my Manifest:

    <addin src="WebLib.js" legacy="yes" developer="yes">

     <load type="WebLib.Utilities, WebLib" name="WebLib" />

      ….

    Here's my javascript code:

    function ToTitleCase() {

    xweb.document.selection.text = WebLib.ToTitleCase(xweb.document.selection.text);

    }

    Here's my code

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Runtime.InteropServices;

    namespace WebLib

    {

       [ComVisible(true)]

       public class Utilities : Extensibility.IDTExtensibility2

       {

           #region IDTExtensibility2 Members

           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

           #region JavaScript implementation

           public Utilities()

           {

           }

           public String Version()

           {

               return "1.0";

           }

           #endregion

           #region "String Helpers"

           public static String ToTitleCase(string strText)

           {

               string strConvertedText = "";

               try

               {

                   System.Globalization.CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;

                   System.Globalization.TextInfo TextInfo = cultureInfo.TextInfo;

                   strConvertedText = TextInfo.ToTitleCase(strText.ToLower());

               }

               catch

               {

                   strConvertedText = strText;

               }

               return strConvertedText;

           }

           #endregion

       }

    }

    -krr

  12. JD_MSFT says:

    We are calling the instance, and the static keyword is not going to work here, squash that, rebuild, replace, restart Expression Web and things should work (quick glance looks good otherwise).

    Wrote a primer and just published on my blog:

    http://blogs.msdn.com/b/jdixon/archive/2010/08/09/calling-managed-code-from-expression-web-4-html-js-extensibility-add-ins.aspx

    HTH

    JD

  13. krr says:

    jdixon,

    Killed the static and bingo it worked!

    I have two more questions.

    1. Can you add a keyboard shortcut to a command?

    It would be nice if we could do something like this in the manifest:

    <menuitem parent="MENU_Format" before="MENU_Format_NewStyle" label="ToTitleCase" shortcut="ctrl-t"/>

    2. How the heck do you add a Separator to a menu?

    Thanks,

    -krr

  14. JD_MSFT says:

    Cool, glad it worked! Both asks (I am pretty sure) did not make V4, sadly. Tooltips did though 🙂

  15. krr says:

    Oh well, maybe they will make v5!

    Thanks for all the great info.

  16. krr says:

    I was asked to convert this to vb which seemed simple enough, however it came up with the following error in the ew log:

    Error: Could not load type 'WebLib.Utilities' from assembly 'WebLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

    Here's the conversion:

    Imports System

    Imports System.Collections.Generic

    Imports System.Linq

    Imports System.Text

    Imports System.Runtime.InteropServices

    Namespace WebLib

       <ComVisible(True)> _

       Public Class Utilities

           Implements Extensibility.IDTExtensibility2

    #Region "IDTExtensibility2 Members"

           Public Sub OnAddInsUpdate(ByRef custom As Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate

               Throw New NotImplementedException()

           End Sub

           Public Sub OnBeginShutdown(ByRef custom As Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown

               Throw New NotImplementedException()

           End Sub

           Public Sub OnConnection(ByVal Application As Object, ByVal ConnectMode As Extensibility.ext_ConnectMode, ByVal AddInInst As Object, ByRef custom As Array) Implements Extensibility.IDTExtensibility2.OnConnection

           End Sub

           Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As Array) Implements Extensibility.IDTExtensibility2.OnDisconnection

               Throw New NotImplementedException()

           End Sub

           Public Sub OnStartupComplete(ByRef custom As Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete

               Throw New NotImplementedException()

           End Sub

    #End Region

    #Region "JavaScript implementation"

           Public Sub New()

           End Sub

           Public Function Version() As String

               Return "1.0"

           End Function

    #End Region

    #Region "String Helpers"

           Public Function ToTitleCase(ByVal strText As String) As String

               Dim strConvertedText As String = ""

               Try

                   Dim cultureInfo As System.Globalization.CultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture

                   Dim TextInfo As System.Globalization.TextInfo = cultureInfo.TextInfo

                   strConvertedText = TextInfo.ToTitleCase(strText.ToLower())

               Catch

                   strConvertedText = strText

               End Try

               Return strConvertedText

           End Function

    #End Region

       End Class

    End Namespace

    -krr

  17. JD_MSFT says:

    Ping me on my blog, not a great place for this one 🙂

    blogs.msdn.com/…/jdixon

  18. codeaholic says:

    @mkapke.  We have an Extension/add-in that originally existed on FrontPage 95, and ported to Expression 1, recompiled in Expression 2.  It uses the Microsoft Add-in extensibility and the office-addin library version 12.  However, with Expression web 3 and 4, no new Office-addin library was provided for Version 13.  Also, when we replace the Microsoft Expression 2 .dlls with references to the Expression 4 .dlls, the application will not recomplie and not even all the .dlls will readd.  So, something did completely change between Expression 2 and expression 3 in terms of it being integrated as a simple office addin.

    I appreciate your Visual Studio Template but its written in C# and since its worthless to VB.NET programmers.  You need a template written in VB.NET PLEASE !

  19. Closing tag </load> says:

    Closing tag </load> is not seen in the code.

  20. Andy says:

    Hello.

    I downloaded MEW 4 few weeks ago and I like it, but I simply cannot find the Add in builder anywhere on the web.

    Does anyone know any download link that works?

    Thanks a lot.