我不确定我的Angular应用程序调用WebAPI是否存在CORS问题。我的ASP.Net MVC / Angular App1和Web API托管在同一个IIS服务器上。例如,App1的网址为https://example.com/App1。 Web API网址为http://example.com/wcf_webapi/clinicaluserprofile/api/ {userNetworkName}。在MVC视图页面上有一个< div ng-include =" '角度视图模板的路径' ">< / div> 使用$ resource从WebAPI获取数据。在Visual Studio 2013 IDE中,当我按F5在我的开发工作站上进行调试时,一切都按预期工作。我可以在IE Developer Tools'中看到对Web API的调用。网络选项卡。但是,当我将App1发布到该IIS服务器时,似乎没有进行Web API调用。相反,我在IE Developer Tools控制台中看到了访问被拒绝。我在不同文件夹中的同一个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);
});
})();
&#13;
这是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(
// )
})();
&#13;
这是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*/
}
}
})();
&#13;
这是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>
&#13;
这是controller.js,其中&#34;访问被拒绝&#34;发生在线
userProfileFactory.getUserProfile()。得到({ 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;
}
);
}
}
})();
&#13;
答案 0 :(得分:1)
在App1中,在程序包管理器控制台中运行此命令
Install-Package Microsoft.AspNet.WebApi.Cors
在此行之前的webapiconfig.cs中添加此config.EnableCors();
- &gt; config.Routes.MapHttpRoute
在控制器[EnableCors(origins: "*", headers: "*", methods: "*")]
中添加此属性。这样做将允许您接受来自任何域的请求与任何Http动词。
另外,我建议您为App2中的所有httpRequest创建一个包装器,并将其注入您控制器的工厂服务中。
答案 1 :(得分:1)
谢谢大家的帮助。我刚刚发现MVC global.asax.cs添加了一个过滤器来要求HTTPS,但是config.js中的WebAPI端点正在使用HTTP。因此发生了CORS问题。在此示例中,App1的网址为https://example.com/App1。 WebAPI是http://example.com/wcf_webapi/clinicaluserprofile/api/ {userNetworkName}。我将WebAPI端点更改为使用HTTPS协议,然后一切正常。