首页 文章

使用$ resource调用远程webapi时,angularjs访问被拒绝

提问于
浏览
1

我不确定我的Angular应用程序调用WebAPI是否存在CORS问题 . 我的ASP.Net MVC / Angular App1和Web API托管在同一个IIS服务器上 . 例如,App1的url是https://example.com/App1 . Web API网址是http://example.com/wcf_webapi/clinicaluserprofile/api/ . 在MVC视图页面上有一个 <div ng-include=" 'path to an angular view template' "></div> ,它使用$ resource从WebAPI获取数据 . 在Visual Studio 2013 IDE中,当我按F5在我的开发工作站上进行调试时,一切都按预期工作 . 我可以在IE Developer Tools中看到对Web API的调用' Network tab. However, when I publish App1 to that IIS server, the Web API call doesn' . 相反,我在IE Developer Tools Console中看到了 access denied . 我在不同文件夹中的同一个IIS上有另一个MVC / Angular App2,几乎相同的Angular代码 . App2的网址是https://example.com/App2 . 它不会被拒绝访问 . 你能帮我吗?谢谢 .

这是Config.js

/// <reference path="C:\Users\myName\Source\Repos\Apps\App1\Scripts/angular.js" />
(function() {
  'use strict'

  var moduleName = 'configModule';
  angular.module(moduleName, []);

  var apiKeyValuePair = {
    'api': {
      centralAdmin: 'http://example.com/wcf_webapi/CentralAdmin/api/',
      fsr: 'http://example.com/FSRManagement/api/',
      userProfile: 'http://example.com/wcf_webapi/clinicaluserprofile/api/'
    }
  }

  var userKeyValuePair = {
    'userAccount': {
      //this is bootstraped and updated in MVC view page <script> block
      userName: ''
    }
  }

  //populate the constant collection
  angular.forEach(apiKeyValuePair, function(val, key) {
    angular.module(moduleName).constant(key, val);
  });
   
  //populate the value collection
  angular.forEach(userKeyValuePair, function(val, key) {
    angular.module(moduleName).value(key, val);
  });
})();

这是App.js

/// <reference path="C:\Users\myName\Source\Repos\Apps\App1\Scripts/angular.js" />
(function() {
  'use strict'
  var moduleName = 'ufsrAppModule';
  var requiredModules = [
    'configModule',
    'fsrFactoryModule',
    'userFsrFactoryModule',
    'userProfileFactoryModule'
  ]
  var app = angular.module(moduleName, requiredModules);
  //  app.config(
  //    )

})();

这是userProfileFactory.js

/// <reference path="C:\Users\myName\Source\Repos\Apps\App1\Scripts/angular.js" />
/// <reference path="C:\Users\myName\Source\Repos\Apps\App1\Scripts/angular-resource.js" />
/// <reference path="../config.js" />

(function() {
  'use strict';

  var moduleName = 'userProfileFactoryModule';
  var factoryName = 'userProfileFactory';
  var requiredModules = ["ngResource", "configModule"];
  var dependencyInjection = ['$resource', 'api', 'userAccount', internalFunc];

  angular.module(moduleName, requiredModules)
    .factory(factoryName, dependencyInjection);

  function internalFunc($resource, api, userAccount) {
    function getUserProfile() {
      return $resource(api.userProfile + 'user/profile/:NN', {
        NN: '@NN'
      });
    };

    return {
      //usage: userProfileFactory.getUserProfile()
      getUserProfile /*public method*/ : getUserProfile /*internal method above*/
    }
  }
})();

这是MVC视图中包含的Angular模板

<div ng-controller="ufsrController as ufsrCtrl">
  <div class="container">
    <div class="row">
      <div class="widget-body">
        <div class="col-md-6 col-sm-6 fa fa-border">
          <div class="row">
            <div class="col-md-2 col-sm-2"><label class=" form-label">Facility:</label></div>
            <div class="col-md-9 col-sm-9" style="padding: 0; margin: 0">
              <select ng-model="ufsrCtrl.facility" name="facility"
                      ng-options="fac.FacilityID as fac.FacilityName for fac in ufsrCtrl.facilities"
                      ng-disabled="(ufsrCtrl.facilities === undefined || ufsrCtrl.facilities.length <= 0)"
                      ng-change="ufsrCtrl.facilityChanged()"
                      class="form-control"></select>
            </div>
            <!--
              <div class="col-md-1 col-sm-1">
                <i ng-show="ufsrCtrl.facilities === undefined || ufsrCtrl.facilities.length <= 0" class="fa fa-refresh fa-spin"></i>
              </div>
            -->
          </div>

          <div class="row">
            <input type="text" name="service" ng-model="ufsrCtrl.service.ServiceName" style="display:none" />
            <div class="col-md-2 col-sm-2"><label class="form-label">Service:</label></div>
            <div class="col-md-9 col-sm-9" style="padding: 0; margin: 0">
              <select ng-model="ufsrCtrl.service" name="serviceId"
                      ng-options="ser.ServiceName for ser in ufsrCtrl.services track by ser.ServiceID "
                      ng-disabled="(ufsrCtrl.services === undefined || ufsrCtrl.services.length <= 0)"
                      ng-change="ufsrCtrl.serviceChanged()"
                      class="form-control">
                <option value="">-- Choose Service --</option>
              </select>
            </div>
            <div class="col-md-1 col-sm-1">
              <i ng-show="ufsrCtrl.services === undefined || ufsrCtrl.services.length <= 0" class="fa fa-refresh fa-spin"></i>
            </div>

          </div>

          <div class="row">
            <input type="text" name="role" ng-model="ufsrCtrl.role.RoleName" style="display:none" />
            <div class="col-md-2 col-sm-2"><label class="form-label">Role:</label></div>
            <div class="col-md-9 col-sm-9" style="padding: 0; margin: 0">
              <select ng-model="ufsrCtrl.role" name="roleId"
                      ng-options="role.RoleName for role in ufsrCtrl.roles track by role.FacilityServiceRoleID"
                      ng-disabled="(ufsrCtrl.roles === undefined || ufsrCtrl.roles.length <= 0)"
                      ng-change="ufsrCtrl.roleChanged()"
                      class="form-control">
                <option value="">-- Choose Role --</option>
              </select>
            </div>
            <div class="col-md-1 col-sm-1" title="select a Service to dismiss me">
              <i ng-show="ufsrCtrl.roles === undefined || ufsrCtrl.roles.length <= 0" class="fa fa-refresh fa-spin"></i>
            </div>


          </div>

          <!--<div class="form-group">
            <button class="btn btn-primary" ng-disabled="(ufsrCtrl.role === undefined)" ng-click="ufsrCtrl.add()" disabled="disabled">
              Add new role {{ufsrCtrl.role.FacilityServiceRoleID}} ({{ufsrCtrl.role.RoleName}})
            </button>
            <span ng-show="(ufsrCtrl.postStatus === true)" class="alert-success"><i class="fa fa-check"></i>Success</span>
            <span ng-show="(ufsrCtrl.postStatus === false)" class="alert-danger"><i class="fa fa-warning"></i>Failure</span>
          </div>-->
        </div>
        <div class="col-md-6 col-sm-6">
          <ul style="list-style-type:disc">
            <li>Select your service then role from the dropdown lists.  The rotating icons will disappear when the selected data is retrieved from the database.</li>
            <li>Check the accuracy of your name and email address and correct them address if incorrect</li>
            <li>Click <b>Send</b> button to send email to the administrators</li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</div>

这是controller.js,其中“访问被拒绝”在线发生

userProfileFactory.getUserProfile() . get({NN:userAccount.networkName}

/// <reference path="C:\Users\myName\Source\Repos\Apps\App1\Scripts/angular.js" />
/// <reference path="UserProfile/userProfileFactory.js" />
(
  function() {
    'use strict';

    var moduleName = 'ufsrAppModule';
    var controllerName = 'ufsrController';
    var dependencyInjection = ['api', 'userAccount', 'userProfileFactory', 'fsrFactory', 'userFsrFactory', internalFunc];

    angular.module(moduleName)
      .controller(controllerName, dependencyInjection);

    function internalFunc(api, userAccount, userProfileFactory, fsrFactory, userFsrFactory) {

      var vm = this; //controller AS in ng-controller, do not use $scope

      vm.postStatus = undefined;
      vm.deleteStatus = undefined;
      vm.showFSRSpinner = true;

      //the following REST call to the WebAPI is access denied
      userProfileFactory.getUserProfile().get({
          NN: userAccount.networkName
        },
        function(data) {
          //debugger;

          vm.userProfile = data;

          if (vm.userProfile != undefined || vm.userProfile != null) {
            if (vm.userProfile.SimpleUser != undefined)
              vm.userId = vm.userProfile.SimpleUser.UserID;

            if (vm.userProfile.UserFSRs != null && vm.userProfile.UserFSRs !== undefined) {
              if (vm.userProfile.UserFSRs.length > 1) {
                vm.role === undefined;
                vm.deletable = true;
              }
            }

            //due to the userProfileFactory uses async to make REST api call
            //the vm.userProfile.InferredFacility won't be avaialbe until the success callback is executed
            //and until then the vm.facilities will make api call to fsrFactory.facility().get()

            vm.facility; //for binding to facility dropdown selected item (ng-model)

            //the fsrFacility.facility().get() returns an object
            //but the vm.facilities is bound to ng-option in the <select> element which expects an array
            //so the returned object needs to be wrapped in aryFacility array

            var aryFacility = [];

            var tempFacilityObj = fsrFactory.facility().get({
              id: vm.userProfile.InferredFacility.FacilityID
            }); //get only facility of the user's inferred facility
            aryFacility.push(tempFacilityObj);
            console.log(aryFacility);

            vm.facilities = aryFacility;
            console.log(vm.facilities);

            vm.facility = vm.userProfile.InferredFacility.FacilityID;
            console.log(vm.facility);

            vm.postStatus = undefined;
            vm.services = undefined;
            vm.roles = undefined;
            vm.services = fsrFactory.service().query({
              FacilityID: vm.facility
            });
          }
        }
      );

      vm.facilityChanged = function() {
        vm.postStatus = undefined;
        vm.services = undefined;
        vm.roles = undefined;
        vm.services = fsrFactory.service().query({
          FacilityID: vm.facility
        });
      }

      vm.service; //for binding to service dropdown selected item (ng-model)
      vm.serviceChanged = function() {
        console.log(vm.service);
        vm.postStatus = undefined;
        vm.roles = undefined;
        vm.roles = fsrFactory.role().query({
          FacilityID: vm.facility,
          ServiceID: vm.service.ServiceID
        });
      }

      vm.role; //for binding to role dropdown selected item (ng-model)
      vm.roleChanged = function() {
        console.log(vm.role);
        vm.postStatus = undefined;
      }

      vm.add = function() {
        //debugger;
        vm.postStatus = undefined;
        vm.deleteStatus = undefined;
        userFsrFactory.addUserFSR().save({
            userId: vm.userId,
            fsrId: vm.role.FacilityServiceRoleID
          },
          function() {
            alert("New role added");
            vm.postStatus = true;

            //vm.userProfile.UserFSRs.push({
            //  UserFacilityServiceRoleID: vm.userId,
            //  dtoFSR: {
            //    FacilityName: vm.facility.FacilityName,
            //    ServiceName: vm.service.ServiceName,
            //    RoleName: vm.role.RoleName,
            //  }
            //})
            userProfileFactory.getUserProfile().get(function(data) {
              vm.userProfile = data; //after add requery userProfile to get the list of user FSR
              if (vm.userProfile.UserFSRs != undefined && vm.userProfile.UserFSRs.length > 1) {
                vm.deletable = true;
                vm.disabled = false;
                vm.role = undefined;
              }
            });
          },
          function() {
            alert("add role failed");
            vm.postStatus = false;
          });
      }

      vm.delete = function(idx, ufsrId) {
        vm.postStatus = undefined;
        vm.deleteStatus = undefined;
        userFsrDeleteFactory.deleteUserFSR().delete({
            userId: vm.userId,
            ufsrId: ufsrId
          },
          function() {
            alert("Delete Succeeded");
            vm.deleteStatus = true;

            vm.userProfile.UserFSRs.splice(idx, 1); //remove from the fsr array
            if (vm.userProfile.UserFSRs != undefined && vm.userProfile.UserFSRs.length > 1)
              vm.deletable = true;

            //$route.reload();
            //location.reload(true); //jquery
          },
          function() {
            alert("Delete failed")
            vm.deleteStatus = false;
          }
        );
      }
    }
  })();

2 回答

  • 1

    谢谢大家的帮助 . 我刚刚发现MVC global.asax.cs添加了一个需要HTTPS的过滤器,但是config.js中的WebAPI endpoints 正在使用HTTP . 因此发生了CORS问题 . 在此示例中,App1的URL为https://example.com/App1 . WebAPI是http://example.com/wcf_webapi/clinicaluserprofile/api/ . 我将WebAPI endpoints 更改为使用HTTPS协议,然后一切正常 .

  • 1

    在App1中,在包管理器控制台中运行此命令

    Install-Package Microsoft.AspNet.WebApi.Cors
    

    在此行之前的webapiconfig.cs中添加此 config.EnableCors(); - > config.Routes.MapHttpRoute

    在控制器 [EnableCors(origins: "*", headers: "*", methods: "*")] 中添加此属性 . 这样做将允许您接受来自任何域的请求与任何Http动词 .

    另外,我建议你为App2中的所有httpRequest创建一个包装器,并将其注入到控制器的工厂服务中 .

    Reference

相关问题