我正在为Xamarin.UWP
开发一个应用程序,它试图将Javascript注入本地html文件(uri:ms-appdata:///local/index.html),就像这样:
async void OnWebViewNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
if (args.IsSuccess)
{
// Inject JS script
if (Control != null && Element != null)
{
foreach (var f in Element.RegisteredFunctions.Where(ff => !ff.IsInjected))
{
await Control.InvokeScriptAsync("eval", new[] { string.Format(JavaScriptFunctionTemplate, f.Name) });
f.Injected();
}
}
}
}
然后,当调用Javascript方法时,这将调用OnWebViewScriptNotify
方法,以便我可以在我的应用程序中处理请求。
问题是这对某些kind of security reasons不起作用:
这是我们做出的一项政策决定,我们对此有所反馈 重新评估它。如果您使用,同样的限制不适用 NavigateToStreamUri与解析器对象一起使用。在内部那是 无论如何,ms-appdata:///会发生什么。
然后我试着在这种情况下建议使用如下所述的解析器:https://stackoverflow.com/a/18979635/2987066
但这会对性能产生巨大影响,因为它会不断将所有文件转换为要加载的流,以及某些页面加载不正确。
然后我使用AddWebAllowedObject
方法,如下所示:
private void Control_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
if (Control != null && Element != null)
{
foreach (var f in Element.RegisteredFunctions)
{
var communicator = new HtmlCommunicator(f);
Control.AddWebAllowedObject("HtmlCommunicator", communicator);
}
}
}
HtmlCommunicator
的位置:
[AllowForWeb]
public sealed class HtmlCommunicator
{
public JSFunctionInjection Function { get; set; }
public HtmlCommunicator(JSFunctionInjection function)
{
Function = function;
}
public void Fred()
{
var d = 2;
//Do something with Function
}
}
在我的HTML中就是这样:
try { window.HtmlCommunicator.Fred(); } catch (err) { }
但这也不起作用。
那么有办法解决这个严重的限制吗?
答案 0 :(得分:0)
所以我找到了这个答案:C# class attributes not accessible in Javascript
它说:
我认为您需要定义以较低的方式开头的方法名称 案件特征。
例如:将GetIPAddress更改为getIPAddress。
我测试了它,发现我是否使用大写名称 'GetIPAddress',它不起作用。但是如果我使用getIPAddress,它就可以工作。
所以我尝试了这个:
我根据建议here创建了一个Windows Runtime Component
类型的新项目,并将我的方法名称更改为小写,因此我有:
[AllowForWeb]
public sealed class HtmlCommunicator
{
public HtmlCommunicator()
{
}
public void fred()
{
var d = 2;
//Do something with Function
}
}
在我的javascript中,我有了:
try { window.HtmlCommunicator.fred(); } catch (err) { }
在我的主要UWP项目中,我引用了新的Windows Runtime Component
库并具有以下内容:
public HtmlCommunicator communicator { get; set; }
private void Control_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
if (Control != null && Element != null)
{
communicator = new HtmlCommunicator();
Control.AddWebAllowedObject("HtmlCommunicator", communicator);
}
}
这很有效!