带有 WebApi 的 Dnn SPA 模块适用于管理员,但不适用于注册用户
Dnn SPA module with WebApi works for administrators but not for Registered Users
我有一个基于 Angular6 的工作 Dnn SPA 模块,它调用 Dnn 服务框架。所有这些都非常适合属于管理员角色的用户,但是当用户仅以所有用户或注册用户角色登录时,我们会在 Chrome 开发控制台中收到以下错误:
ERROR TypeError: Cannot read property 'length' of undefined
at http.js:108
at Array.forEach ()
at HttpHeaders.lazyInit (http.js:102)
at HttpHeaders.push../node_modules/@angular/common/fesm5/http.js.HttpHeaders.init
(http.js:166)
at HttpHeaders.push../node_modules/@angular/common/fesm5/http.js.HttpHeaders.forEach
(http.js:235)
at Observable._subscribe (http.js:1435)
at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe
(ReplaySubject.js:83)
at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe
(ReplaySubject.js:69)
at tryCatch.js:17
at subscribeToResult (index.js:1)
我想也许出于某种原因我们的拦截器没有添加 HTTPHeaders,但是查看“网络”选项卡,我们的调用 none 一直在进行。
解决问题的尝试:
检查 Angular 是否正在启动
我的 Angular 应用程序中有一个应用程序初始值设定项,所以我向它添加了一个控制台日志,它正在被触发:
export function appInitializer(configurationService: ConfigurationService) {
configurationService.configuration.antiforgeryToken = dnnService.framework.getAntiForgeryValue();
configurationService.apiPath = dnnService.framework.getServiceRoot(dnnService.path);
configurationService.configuration.moduleId = dnnService.moduleId;
configurationService.configuration.tabId = dnnService.tabId;
configurationService.configuration.tabModuleId = dnnService.tabModuleId;
console.log('configuration for app initializer: ', configurationService);
return () => true;
}
检查防伪令牌
应该添加的一个HTTPHeader是防伪令牌
dnnService.framework.getAntiForgeryValue()
出于某种原因,此值对于注册用户为空,而对于管理员用户则具有正确的值。但是,如果甚至没有拨打电话,那么我不确定这可能是问题的原因。
为 WebApi 调用添加了额外的日志记录
我发现了一个可疑但无法link解决问题的日志条目:
[WARN] DotNetNuke.Entities.Tabs.TabController - Invalid tabId -1 of
portal 0
更改了所有 WebApi 控制器的访问级别
我将所有 DnnModuleAuthorisation 更改为以下内容:
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.Anonymous)]
我也试过了
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
没什么区别。
检查是否触发了对 HTTP WebApi 端点的首次调用
在 ngDoBootstrap 中,我进行了第一个 HTTP 调用,这是停止运行的地方,所以这会让我相信 Angular 中实际上存在问题:
ngDoBootstrap(app) {
console.log('about to get settings');
this.settingsService.getSettings().subscribe((settings: Settings) => {
console.log('fired call to get settings'); //<- Never gets here
});
}
getSettings().subscribe 中的 console.log 永远不会触发!
任何关于要检查的内容的提示或指导都会很棒。
也许您需要手动添加 jQuery 库。在管理员模式下,这些由框架自动添加。这就是为什么你在那里没有错误。
using DotNetNuke.Framework;
using DotNetNuke.Common;
//7.2 and lower
if (Globals.DataBaseVersion.Major < 7 || (Globals.DataBaseVersion.Major == 7 && Globals.DataBaseVersion.Minor < 2))
{
jQuery.RequestDnnPluginsRegistration();
}
else
{
//7.3 and higher
JavaScriptLibraries.JavaScript.RequestRegistration(JavaScriptLibraries.CommonJs.DnnPlugins);
}
看看这个 page。您可以将防伪令牌加载到您的模板中,然后在您的服务中检索它。自从我使用 DNN 以来已经有一段时间了,但我记得遇到过这个完全相同的问题并且有一个简单的修复方法。
编辑:我能够联系并检索我为此编写的代码。这是我在纯 SPA 模块中检索 API 的方式(仅 HTML/JS):
[JavaScript:{ jsname: "AngularJs" }]
[JavaScript:{ path: "~/DesktopModules/module/dist/app.build.js"}]
<div id="root"
data-module-id="[ModuleContext:ModuleId]"
data-is-superuser="[ModuleContext:IsSuperUser]"
data-anti-forgery-token="[AntiForgeryToken:true]"
ng-cloak="true"
ng-switch="{{'[ModuleContext:IsSuperUser]'.toLowerCase()}}">
<!-- non-admins -->
<div ng-switch-when="false">
<app></app>
</div>
<!-- admins -->
<div ng-switch-when="true">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title" ng-bind="::'App'"></h3>
</div>
</div>
</div>
</div>
<script>
angular.element(function () {
angular.bootstrap(document.getElementById('root'), ['App']);
});
</script>
原来是RequestVerificationToken。出于某种原因,Dnn 只为管理员输出令牌,或者当皮肤 (?) 中出现搜索框时,我已将其删除。
解决方法是添加搜索并使用样式隐藏它。例如。
<div id="search-top" style="display:none !important">
<dnn:SEARCH ID="dnnSearch2" runat="server" ShowSite="false" ShowWeb="false" EnableTheming="true" Submit="Search" CssClass="SearchButton" />
</div>
我已经用非管理员用户测试过这个并且它有效。
有关详细信息,请参阅相关 Dnn 9 bug posted on DnnTracker:
我有一个基于 Angular6 的工作 Dnn SPA 模块,它调用 Dnn 服务框架。所有这些都非常适合属于管理员角色的用户,但是当用户仅以所有用户或注册用户角色登录时,我们会在 Chrome 开发控制台中收到以下错误:
ERROR TypeError: Cannot read property 'length' of undefined at http.js:108 at Array.forEach () at HttpHeaders.lazyInit (http.js:102) at HttpHeaders.push../node_modules/@angular/common/fesm5/http.js.HttpHeaders.init (http.js:166) at HttpHeaders.push../node_modules/@angular/common/fesm5/http.js.HttpHeaders.forEach (http.js:235) at Observable._subscribe (http.js:1435) at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (ReplaySubject.js:83) at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (ReplaySubject.js:69) at tryCatch.js:17 at subscribeToResult (index.js:1)
我想也许出于某种原因我们的拦截器没有添加 HTTPHeaders,但是查看“网络”选项卡,我们的调用 none 一直在进行。
解决问题的尝试:
检查 Angular 是否正在启动
我的 Angular 应用程序中有一个应用程序初始值设定项,所以我向它添加了一个控制台日志,它正在被触发:
export function appInitializer(configurationService: ConfigurationService) {
configurationService.configuration.antiforgeryToken = dnnService.framework.getAntiForgeryValue();
configurationService.apiPath = dnnService.framework.getServiceRoot(dnnService.path);
configurationService.configuration.moduleId = dnnService.moduleId;
configurationService.configuration.tabId = dnnService.tabId;
configurationService.configuration.tabModuleId = dnnService.tabModuleId;
console.log('configuration for app initializer: ', configurationService);
return () => true;
}
检查防伪令牌
应该添加的一个HTTPHeader是防伪令牌
dnnService.framework.getAntiForgeryValue()
出于某种原因,此值对于注册用户为空,而对于管理员用户则具有正确的值。但是,如果甚至没有拨打电话,那么我不确定这可能是问题的原因。
为 WebApi 调用添加了额外的日志记录
我发现了一个可疑但无法link解决问题的日志条目:
[WARN] DotNetNuke.Entities.Tabs.TabController - Invalid tabId -1 of portal 0
更改了所有 WebApi 控制器的访问级别
我将所有 DnnModuleAuthorisation 更改为以下内容:
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.Anonymous)]
我也试过了
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
没什么区别。
检查是否触发了对 HTTP WebApi 端点的首次调用
在 ngDoBootstrap 中,我进行了第一个 HTTP 调用,这是停止运行的地方,所以这会让我相信 Angular 中实际上存在问题:
ngDoBootstrap(app) {
console.log('about to get settings');
this.settingsService.getSettings().subscribe((settings: Settings) => {
console.log('fired call to get settings'); //<- Never gets here
});
}
getSettings().subscribe 中的 console.log 永远不会触发!
任何关于要检查的内容的提示或指导都会很棒。
也许您需要手动添加 jQuery 库。在管理员模式下,这些由框架自动添加。这就是为什么你在那里没有错误。
using DotNetNuke.Framework;
using DotNetNuke.Common;
//7.2 and lower
if (Globals.DataBaseVersion.Major < 7 || (Globals.DataBaseVersion.Major == 7 && Globals.DataBaseVersion.Minor < 2))
{
jQuery.RequestDnnPluginsRegistration();
}
else
{
//7.3 and higher
JavaScriptLibraries.JavaScript.RequestRegistration(JavaScriptLibraries.CommonJs.DnnPlugins);
}
看看这个 page。您可以将防伪令牌加载到您的模板中,然后在您的服务中检索它。自从我使用 DNN 以来已经有一段时间了,但我记得遇到过这个完全相同的问题并且有一个简单的修复方法。
编辑:我能够联系并检索我为此编写的代码。这是我在纯 SPA 模块中检索 API 的方式(仅 HTML/JS):
[JavaScript:{ jsname: "AngularJs" }]
[JavaScript:{ path: "~/DesktopModules/module/dist/app.build.js"}]
<div id="root"
data-module-id="[ModuleContext:ModuleId]"
data-is-superuser="[ModuleContext:IsSuperUser]"
data-anti-forgery-token="[AntiForgeryToken:true]"
ng-cloak="true"
ng-switch="{{'[ModuleContext:IsSuperUser]'.toLowerCase()}}">
<!-- non-admins -->
<div ng-switch-when="false">
<app></app>
</div>
<!-- admins -->
<div ng-switch-when="true">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title" ng-bind="::'App'"></h3>
</div>
</div>
</div>
</div>
<script>
angular.element(function () {
angular.bootstrap(document.getElementById('root'), ['App']);
});
</script>
原来是RequestVerificationToken。出于某种原因,Dnn 只为管理员输出令牌,或者当皮肤 (?) 中出现搜索框时,我已将其删除。
解决方法是添加搜索并使用样式隐藏它。例如。
<div id="search-top" style="display:none !important">
<dnn:SEARCH ID="dnnSearch2" runat="server" ShowSite="false" ShowWeb="false" EnableTheming="true" Submit="Search" CssClass="SearchButton" />
</div>
我已经用非管理员用户测试过这个并且它有效。
有关详细信息,请参阅相关 Dnn 9 bug posted on DnnTracker: