Search code examples
javascriptc#html-agility-packclearscript

How to expose HtmlAgilityPack.CssSelectors into ClearScript


Context: Azure, C#, ClearScript, JavaScript, HtmlAgilityPack, HtmlAgilityPack.CssSelectors

I do this a lot: add scripting to C# apps using ClearScript. Ordinarily this just works.

...
using Microsoft.ClearScript;
using Microsoft.ClearScript.Windows;
...
    class Program
    {
        static JScriptEngine JSengine = null;
...
                    JSengine = new JScriptEngine(WindowsScriptEngineFlags.EnableDebugging | WindowsScriptEngineFlags.EnableJITDebugging);
....
                    JSengine.AddHostType("CSHtmlDocument", typeof(HtmlAgilityPack.HtmlDocument));
...

and then later, in the JavaScript code itself, there are things like

...
var hap = new CSHtmlDocument();
hap.LoadHtml(html);
...

So this is going really well until I add HtmlAgilityPack.CssSelectors into the mix. On the C# side, this adds extra methods to the HtmlDocument object, specifically QuerySelector and QuerySelectorAll. They're visible on the C# side. However, on the JavaScript side they're not and code such as

...
var selection = hap.QuerySelector(".reduced");
...

throws an error and looking at the object from a debugging session in Visual Studio 2015 shows no QuerySelector method in the hap var.

So what's the story? Is it a ClearScript issue or a C# issue? And what do I do about it? I'm quite happy to write a wrapper class, I was just expecting everything to work as before.


Solution

  • These new methods are most likely extension methods defined by a particular class. To make them accessible from script code, you must expose that class to the script engine.

    EDIT: I'm not familiar with them, but it looks like the methods you're talking about are provided by the HapCssExtensionMethods class (or something very similar). To expose the methods, simply expose the class:

    // C#
    JSengine.AddHostType(typeof(HapCssExtensionMethods));
    

    Once you've done that, your JavaScript sample above should work as is.