具有WebApi的Dnn SPA模块适用于管理员,但不适用于注册用户

时间:2018-11-08 10:44:10

标签: angular asp.net-web-api single-page-application dotnetnuke

我有一个基于Angular 6的Dnn SPA模块,该模块可以调用Dnn服务框架。所有这些功能对于属于管理员角色的用户来说都是完美的,但是当用户仅使用“所有用户”或“注册用户”角色登录时,我们会在Chrome Dev Console中出现以下错误:

  

错误TypeError:无法读取未定义的属性“ length”       在http.js:108       在Array.forEach()       在HttpHeaders.lazyInit(http.js:102)       在HttpHeaders.push ../ node_modules/@angular/common/fesm5/http.js.HttpHeaders.init中   (http.js:166)       在HttpHeaders.push ../ node_modules/@angular/common/fesm5/http.js.HttpHeaders.forEach中   (http.js:235)       在Observable._subscribe(http.js:1435)       在Observable.push ../ node_modules / rxjs / _esm5 / internal / Observable.js.Observable._trySubscribe中   (ReplaySubject.js:83)       在Observable.push ../ node_modules / rxjs / _esm5 / internal / Observable.js.Observable.subscribe   (ReplaySubject.js:69)       在tryCatch.js:17       在subscriptionToResult(index.js:1)

我认为,也许由于某些原因我们的拦截器未添加HTTPHeaders,但是在“网络”选项卡上,我们都没有进行任何调用。

尝试解决问题:

检查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调用添加了其他日志记录

我发现一个可疑的日志条目,但无法将其链接到问题:

  

[WARN] DotNetNuke.Entities.Tabs.TabController-无效的tabId -1   门户网站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永远不会触发!

关于其他检查内容的任何提示或指导都将非常有用。

3 个答案:

答案 0 :(得分:1)

也许您需要手动添加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);
}

答案 1 :(得分:1)

原来是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

答案 2 :(得分:0)

查看此page。您可以将防伪令牌加载到模板中,然后在服务中检索它。自从我与DNN合作以来已经有一段时间了,但是我记得遇到了同样的问题,并且有一个简单的解决方法。

编辑:我能够伸手找到我为此编写的代码。这是我在纯SPA模块(仅HTML / JS)中检索API的方式:

[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>