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?
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.