带有 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