cefsharp

Translate property names of JavaScript objects passed to .NET in CefSharp


I am using the JavaScript Integration in CefSharp to expose a .NET class to JavaScript.

Simplified Example:

public class Transformer
{
    public Rect Rotate(Rect rect)
        => new Rect { Width = rect.Height, Height = rect.Width };
}

public class Rect
{
    public int Width { get; set; }
    public int Height { get; set; }
}

As you can see, everything here is named in PascalCase.

In JavaScript I want everything in camelCase, so I register the class like this:

chromiumWebBrowser.JavascriptObjectRepository.NameConverter = new CamelCaseJavascriptNameConverter();
Transformer transformer = new();
chromiumWebBrowser.JavascriptObjectRepository.Register(nameof(transformer), transformer, BindingOptions.DefaultBinder);

Now in JavaScript I want to use it like this:

await cefSharp.bindObjectAsync("transformer");
let rect = await transformer.rotate({ width: 4, height: 6 });
console.log(`rect: ${rect.width}×${rect.height}`);

However, that does not work correctly. The log output of this is rect: 0×0 because the properties of the parameter are not bound correctly because of the difference in casing. The following workarounds, which I want to avoid, make it work: change JS object to { Width: 4, Height: 6 } or change .NET property names to camelCase.

The reason, as far as I can tell, is that the registered NameConverter is only used to convert

It is NOT used to convert

Is there a way I can achieve what I want without the mentioned workarounds, or would this be a feature request for CefSharp?


Solution

  • For this to work correctly the name converter must be assigned in two places, as seen in the following example:

    Transformer transformer = new();
    
    CamelCaseJavascriptNameConverter nameConverter = new();
    
    // here it is used for the method names of all registered objects and the property names of objects returned from .NET to JavaScript
    chromiumWebBrowser.JavascriptObjectRepository.NameConverter = nameConverter;
    
    // here it is used for property names when binding objects that are  passed from JavaScript to .NET
    chromiumWebBrowser.JavascriptObjectRepository.Register(
        nameof(transformer),
        transformer,
        new BindingOptions { Binder = new DefaultBinder(nameConverter) });
    

    In this case it would also be possible to assign the static DefaultBinder.Instance to the BindingOptions.Binder property, because it uses the CamelCaseJavascriptNameConverter implicitly.