For testing purposes, two web apps are set up, a "client" app (localhost) and a server app (Azure web app). The client sends an AJAX request to the server and receives a cookie in response. Then it makes another AJAX call to the server, but there's no cookie in the request, it's missing.
Here's the server configuration (CORS setup; https://localhost:44316 is my "client" URL):
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => {
o.AddPolicy("policy1", builder =>
builder.WithOrigins("https://localhost:44316")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("policy1");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Here's the first controller, returning the cookie:
[Route("api/[controller]")]
[ApiController]
public class AController : ControllerBase
{
[HttpPost]
public IActionResult Post()
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Expires = DateTime.Now.AddMinutes(10),
SameSite = SameSiteMode.None
};
Response.Cookies.Append("mykey", "myvalue", cookieOptions);
return Ok();
}
}
Here's the second controller, which should receive the cookie (but it doesn't):
[Route("api/[controller]")]
[ApiController]
public class BController : ControllerBase
{
[HttpPost]
public IActionResult Post()
{
var x = Request.Cookies;
return Ok(JsonConvert.SerializeObject(x));
}
}
And here's the calling script from the "client" (first and second call, respectively):
function Go()
{
$.ajax({
url: 'https://somewebsite.azurewebsites.net/api/a',
type: 'post',
xhrFields: {
withCredentials: true
},
success: function (data, textStatus, jQxhr)
{
console.log(data);
},
error: function (jqXhr, textStatus, errorThrown)
{
console.log(errorThrown);
}
});
}
function Go2()
{
$.ajax({
url: 'https://somewebsite.azurewebsites.net/api/b',
type: 'post',
xhrFields: {
withCredentials: true
},
success: function (data, textStatus, jQxhr)
{
console.log(data);
},
error: function (jqXhr, textStatus, errorThrown)
{
console.log(errorThrown);
}
});
}
Does anyone have an idea what could be the problem here?
As this document said :
Cookies that assert SameSite=None must also be marked as Secure
But you didn't, so use this instead:
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Expires = DateTime.Now.AddMinutes(10),
SameSite = SameSiteMode.None,
Secure = true
};
And this is my test result:
I quite like the style of what you are doing here in terms of an SPA getting cookies from an API. Some recommendations below, based on experience at dealing with these issues.
PROBLEM
You are calling from the browser to an API in a different domain, meaning the cookie is third party and modern browsers will drop it aggressively.
Web Origin: localhost:44316
API Domain: myazurewebapp.com
SameSite=None is the theoretical solution from standards docs but these often do not explain current browser behaviour:
You have to set the Secure property, as Jason Pan says
But it will still not work in the Safari browser and maybe some others
Expect cross site cookies to be dropped in all browsers in the near future
SOLUTION
The preferred option is to design hosting domains so that only first party cookies are used, and many software companies have done this. It can be done by running the API in a child or sibling domain of the web origin:
Web Origin: www.example.com
API Domain: api.example.com
On a developer PC you can do this simply by updating your hosts file. Note also that you can run web and API components on different ports and they will remain same site:
127.0.0.1 localhost www.example.com api.example.com
:1 localhost
The browser will then still be making CORS requests, but will consider the cookie issued by the API to be in the same site as the web origin. You can then also change the cookie settings to use SameSite=strict, for best security.
FURTHER INFO
At Curity we have published some recent articles on web security that are closely related to your question, since secure cookies used in OpenID Connect security have also had to deal with dropped cookie problems:
Code
Articles
You should know AddTransient, AddScoped and AddSingleton first. Below post will useful to you.
AddTransient, AddScoped and AddSingleton Services Differences
And you need use AddSingleton, and you will get the cookie value by key.
Offical blogs: How to work with cookies in ASP.NET Core
It works for me, you can find sample code in the blogs I provided.
My Test
1. test code
2. test result in another controller.
Related
I am trying to make an API requests that deletes an entity in the backend. My spring server and node.js server are running on different ports.
When I try a fetch request with cors enabled (mode: "cors") I get an error that the request was blocked by the cors policy. When I disabel cors (mode: "no-cors"), I get the following error:
Failed to execute 'fetch' on 'Window': 'DELETE' is unsupported in no-cors mode.
The code for the request:
export async function deleteOneProcessType(id) {
let ret = await fetch(`${restUri}${uri}/${id}`, {
method: "DELETE",
mode: "no-cors"
})
}
I have similar POST and GET methods whith cors disabled that work just fine.
No need to set mode: "no-cors"
Indeed you just need toadjust your backend in order to allow your request
To do so add a WebMvcConfigurer Bean
You can do so using a Configuration class for instance.
You can refer to https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
As mentionned in the documentation by default only GET and POST requests are allowed.
Then you need to allow DELETE as well
Finally you should have something like that :
#Bean
public WebMvcConfigurer corsController()
{
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("[Your_backend_server_URI_here]/**")
.allowedOrigins("[Your_frontend_URL_here]")
.allowedMethods("PUT","DELETE","GET","POST");
}
};
}
POST and GET are considered simple requests where you can use mode: "no-cors" . You cannot do this with DELETE and PUT for example. I suggest you to use Proxy server for all your API calls. With a Proxy server you can solve CORS error.
Example: you want to delete an entity to this api: https://test.api.com/customer/1.
In package.json add the following line:
"proxy": "https://test.api.com"
Your request in the component:
export async function deleteOneProcessType(id) {
let ret = await fetch(`/customer/${id}`, {
method: "DELETE"
})
Problem Summary:
I have two web projects that are hosted with different domains. When making ajax call to my Web API project I get the following:
Access to XMLHttpRequest at '' from origin '' has been blocked by CORS
policy: Response to preflight request doesn't pass access control
check: No 'Access-Control-Allow-Origin' header is present on the
requested resource.
First Project - Web API
My first project, which is ASP NET Web API (.Net Framework 4.8)
I enabled CORS globally for everyone just to make sure the tests pass correctly.
In my WebApiConfig file, I have the following line.
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
With using System.Web.Http.Cors; above.
My method has nothing special like attributes since we enabled CORS globally.
[RoutePrefix("api/Test")]
public class TestController : ApiController
{
[Route("RequestConnection")]
[HttpPost]
public IHttpActionResult RequestConnection(MasterOnRequestInputModel inputModel)
{
...some code logic here...
}
}
Second Project - JavaScript with AJAX request
My second projects want to call the mentioned method above in the Web API.
My ajax call looks in the following way:
$.ajax({
type: "POST",
url: myUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: {
'Body': body,
'Head': head,
'Width': width,
'Height': height
},
success: screencastControllerPostSuccess
});
In Chrome the request looks as follow:
What am I doing wrong?
Edit:
Answer
If you guys did, exactly what is written above, you should have absolutely no problems with CORS.
My problem was with the WAF our company is using. The WAF was denying my request due to it being a potential attack. And this is because I was sending HTML elements in the request body. Together with my system administrator colleagues, we fixed the issue.
So the interesting part is, that after my request is denied from the WAF it returns an error as if the problem is with CORS. That is because indeed the request is cross-domain, but the WAF generic response after denying a request doesn't have the Access-Control-Allow-Origin header.
Have a look at the WAF of www.asp-waf.com, you will find it quite easy to work with also finding issues like that are easy as you just register with the OnGuardAction event and you can see what and why it would be blocked by debugging it or sending it to the log.
we do this by using the base class FireWallBase like this
public class MyFireWall : FireWallBase
{
private readonly ILogger<MyFireWall> _logger;
private bool _agreeWithFirewall = true;
public MyFireWall(
//enable accessing AppConfig
IConfiguration configuration
//allow DI to provide interfaces to base class
, ILoggerFactory? loggerFactory = null, IMemoryCache? memoryCache = null
, IIncidentDatabase? incidentDatabase = null, IWhoisRepository? whoisRepository = null, ISubscriptionsRepository? subscriptions = null
, IEmailReportDesination? emailReportDesination = null, IDatabaseReportDestination? databaseReportDestination = null
, ILoggerReportDesination? loggerReportDestination = null, IFireWallDiskLoggerDestination? diskLoggerDestination = null
, IEventLogReporting? eventLogReporting = null, IGeoFactory? geoFactory = null, ILatLongRepository? latLongRepository = null
, IResetRepository? resetRepository = null)
: base(loggerFactory, memoryCache, incidentDatabase, whoisRepository, subscriptions, emailReportDesination, databaseReportDestination
, loggerReportDestination, diskLoggerDestination, eventLogReporting, geoFactory, latLongRepository, resetRepository)
{
var section = configuration.GetSection("FireWall");
if (section.Exists())
{
_isReccommendOnly = section.GetValue<bool>("AgreeWithFirewall");
}
base.Trigger_OnFireWallCreated(this);
OnIncident += MyFireWall_OnIncident;
OnGuardAction += MyFireWall_OnGuardAction;
OnUserTypeChange += MyFireWall_OnUserTypeChange;
_logger = loggerFactory.CreateLogger<MyFireWall>();
}
private void MyFireWall_OnUserTypeChange(object? sender, Walter.Web.FireWall.EventArguments.UserTypeChangedEventArgs e)
{
_logger?.LogCritical("{oldType} : {newType}\n {route}\n Rules:\n {data}"
, e.OriginalType
, e.NewType
, e.Rout
, string.Join("\n ", e.Rules)
);
//allow the change
e.Allow = true;
if (e.OriginalType.HasFlag(UserTypes.IsSearchEngine) && e.NewType.HasFlag(UserTypes.IsMalicious))
{
//remove the malicious flag from search engines to not prevent search engines from
//indexing the site
e.NewType &= ~UserTypes.IsMalicious;
}
}
private void MyFireWall_OnGuardAction(object? sender, Walter.Web.FireWall.EventArguments.GuardActionEventArgs e)
{
_logger?.LogCritical("{Method} {page} : {route}\n {action}:{RuleNr}\n Reasons:{Reason}\n {data}"
, e.Page.Method
, e.Page.OriginalUrl.AbsolutePath
, e.Page.FireWallRoute
, e.Action
, string.Join("\n ", e.Page.PageViolationStack.Select(s => s.ToString()))
);
//allow the firewall to block requests
e.Allow = _agreeWithFirewall;
}
private void MyFireWall_OnIncident(object? sender, Walter.Web.FireWall.EventArguments.FireWallIncidentEventArgs e)
{
_logger?.LogCritical("{Method} {page} : {route}\n {rule}:{RuleNr}\n Reasons:{Reason}\n {data}"
, e.Page.Method
, e.Page.OriginalUrl.AbsolutePath
, e.Page.FireWallRoute
, e.StackEntry.Rule
, e.StackEntry.RuleNr
, e.StackEntry.Reason
, string.Join("\n ", e.Data.Select(s => $"{s.Key}:{s.Value}"))
);
//allow the firewall to raise incidents
e.Allow = _agreeWithFirewall;
}
}
We enable the firewall like everything else in .net web applications via dependency injection. I can enable my own firewall class by using it like so:
services.AddFireWall<MyFireWall>("Token", "Key", new Uri(Configuration["domainUri"], UriKind.Absolute), options =>{
//add your options here
});
In the options, you can configure CORS under options.Rules.Headers but you can do lots more than that.
The firewall is in my NuGet package Walter.Web.FireWall.* There are lot's of add-ons like geography as well as reporting to SMTP timed using a timespan you you can get emails every day and not get flodded with mails when a user got blocked.
I have follow this tutorial of angular 7 to make a CRUD functions. I publish the project into my IIS but I am having an error (Image)
Access to XMLHttpRequest at 'http://192.168.120.178:2030/Api/Employee/UpdateEmployeeDetails/' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried to add the header in Update Code to allow the CORS but its the same.
The error also applies to other functions (Save, Delete)
Angular Code
updateEmployee(employee: Employee): Observable<Employee> {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Credentials': "true",
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Origin': '*'
})
};
return this.http.put<Employee>(this.url + '/UpdateEmployeeDetails/',
employee, httpOptions);
}
API Code
[HttpPut]
[Route("UpdateEmployeeDetails")]
public IHttpActionResult PutEmaployeeMaster(EmployeeDetail employee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
EmployeeDetail objEmp = new EmployeeDetail();
objEmp = objEntity.EmployeeDetails.Find(employee.EmpId);
if (objEmp != null)
{
objEmp.EmpName = employee.EmpName;
objEmp.Address = employee.Address;
objEmp.EmailId = employee.EmailId;
objEmp.DateOfBirth = employee.DateOfBirth;
objEmp.Gender = employee.Gender;
objEmp.PinCode = employee.PinCode;
}
int i = this.objEntity.SaveChanges();
}
catch (Exception)
{
throw;
}
return Ok(employee);
}
But If im running my project using a localhost API its okay. But in publish (IIS) im getting the CORS error. I spent one whole day already but unfortunately I didn't see a solution to my problem.
TL;DR: You actually have the CORS headers in the wrong direction.
The API (server side) needs to be the one returning the CORS headers as a way of signaling to the browser that you expected whatever domain the Angular UI is being served on (client side) to call your API.
See this article from Mozilla about CORS
If you think about it, it doesn't make sense for the client side / browser to set these CORS headers, because the client side can easily be compromised by a bad actor (such as chrome plugin, foreign javascript, etc.), and if the client side was in charge of these CORS headers, it would be really easy to make them be what a hacker wants them to be. Instead, they need to come from the server side - hinted at by the Access-Control-* prefix. It's the server's way of whitelisting domains it expects the front end to access it from.
Another way to think about it would be that I couldn't create a website that directly hit Facebook's API's if they have their CORS headers restricted to only allow *.facebook.com because I don't own that domain. CORS are also a protection layer to prevent bad actors from being able to use your server side APIs and spoof your front end to capture people's data.
if it is .net core go in Startup.cs and serve both back-end and front-end with https and enable CORS
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors();
...
}
public void Configure(IApplicationBuilder app)
{
...
app.UseCors(builder =>
builder.WithOrigins("YOUR_FRONTEND_URL")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
...
}
Source
Web API 2 (Prior Core)
Install-Package Microsoft.AspNet.WebApi.Cors
App_Start\WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute(
origins: "YOUR_FRONTEND_URL",
headers: "*",
methods: "*");
config.EnableCors(cors);
...
}
More Information
I have created a demo using JavaScript for Flickr photo search API.
Now I am converting it to the AngularJs.
I have searched on internet and found below configuration.
Configuration:
myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Service:
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.flickrPhotoSearch = function() {
return $http({
method: 'GET',
url: 'http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=3f807259749363aaa29c76012fa93945&tags=india&format=json&callback=?',
dataType: 'jsonp',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
Controller:
myApp.controller('flickrController', function($scope, dataService) {
$scope.data = null;
dataService.flickrPhotoSearch().then(function(dataResponse) {
$scope.data = dataResponse;
console.log($scope.data);
});
});
But still I got the same error.
Here are some links I tried:
XMLHttpRequest cannot load URL. Origin not allowed by Access-Control-Allow-Origin
http://goo.gl/JuS5B1
You don't. The server you are making the request to has to implement CORS to grant JavaScript from your website access. Your JavaScript can't grant itself permission to access another website.
I had a similar problem and for me it boiled down to adding the following HTTP headers at the response of the receiving end:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
You may prefer not to use the * at the end, but only the domainname of the host sending the data. Like *.example.com
But this is only feasible when you have access to the configuration of the server.
Try using the resource service to consume flickr jsonp:
var MyApp = angular.module('MyApp', ['ng', 'ngResource']);
MyApp.factory('flickrPhotos', function ($resource) {
return $resource('http://api.flickr.com/services/feeds/photos_public.gne', { format: 'json', jsoncallback: 'JSON_CALLBACK' }, { 'load': { 'method': 'JSONP' } });
});
MyApp.directive('masonry', function ($parse) {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-item', columnWidth: $parse(attrs.masonry)(scope) });
}
};
});
MyApp.directive('masonryItem', function () {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.imagesLoaded(function () {
elem.parents('.masonry').masonry('reload');
});
}
};
});
MyApp.controller('MasonryCtrl', function ($scope, flickrPhotos) {
$scope.photos = flickrPhotos.load({ tags: 'dogs' });
});
Template:
<div class="masonry: 240;" ng-controller="MasonryCtrl">
<div class="masonry-item" ng-repeat="item in photos.items">
<img ng-src="{{ item.media.m }}" />
</div>
</div>
This issue occurs because of web application security model policy that is Same Origin Policy Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. That means requester must match the exact host, protocol, and port of requesting site.
We have multiple options to over come this CORS header issue.
Using Proxy - In this solution we will run a proxy such that when request goes through the proxy it will appear like it is some same origin.
If you are using the nodeJS you can use cors-anywhere to do the proxy stuff. https://www.npmjs.com/package/cors-anywhere.
Example:-
var host = process.env.HOST || '0.0.0.0';
var port = process.env.PORT || 8080;
var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
originWhitelist: [], // Allow all origins
requireHeader: ['origin', 'x-requested-with'],
removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
console.log('Running CORS Anywhere on ' + host + ':' + port);
});
JSONP - JSONP is a method for sending JSON data without worrying about cross-domain issues.It does not use the XMLHttpRequest object.It uses the <script> tag instead. https://www.w3schools.com/js/js_json_jsonp.asp
Server Side - On server side we need to enable cross-origin requests.
First we will get the Preflighted requests (OPTIONS) and we need to allow the request that is status code 200 (ok).
Preflighted requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if it uses methods other than GET or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
If you are using the spring just adding the bellow code will resolves the issue.
Here I have disabled the csrf token that doesn't matter enable/disable according to your requirement.
#SpringBootApplication
public class SupplierServicesApplication {
public static void main(String[] args) {
SpringApplication.run(SupplierServicesApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
}
If you are using the spring security use below code along with above code.
#Configuration
#EnableWebSecurity
public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/**").authenticated().and()
.httpBasic();
}
}
I encountered a similar problem like this, problem was with the backend . I was using node server(Express). I had a get request from the frontend(angular) as shown below
onGetUser(){
return this.http.get("http://localhost:3000/user").pipe(map(
(response:Response)=>{
const user =response.json();
return user;
}
))
}
But it gave the following error
This is the backend code written using express without the headers
app.get('/user',async(req,res)=>{
const user=await getuser();
res.send(user);
})
After adding a header to the method problem was solved
app.get('/user',async(req,res)=>{
res.header("Access-Control-Allow-Origin", "*");
const user=await getuser();
res.send(user);
})
You can get more details about Enabling CORS on Node JS
This answer outlines two ways to workaround APIs that don't support CORS:
Use a CORS Proxy
Use JSONP if the API Supports it
One workaround is to use a CORS PROXY:
angular.module("app",[])
.run(function($rootScope,$http) {
var proxy = "//cors-anywhere.herokuapp.com";
var url = "http://api.ipify.org/?format=json";
$http.get(proxy +'/'+ url)
.then(function(response) {
$rootScope.response = response.data;
}).catch(function(response) {
$rootScope.response = 'ERROR: ' + response.status;
})
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
Response = {{response}}
</body>
For more information, see
GitHub: CORS Anywhere
Use JSONP if the API supports it:
var url = "//api.ipify.org/";
var trust = $sce.trustAsResourceUrl(url);
$http.jsonp(trust,{params: {format:'jsonp'}})
.then(function(response) {
console.log(response);
$scope.response = response.data;
}).catch(function(response) {
console.log(response);
$scope.response = 'ERROR: ' + response.status;
})
The DEMO on PLNKR
For more information, see
AngularJS $http Service API Reference - $http.jsonp
Answered by myself.
CORS angular js + restEasy on POST
Well finally I came to this workaround:
The reason it worked with IE is because IE sends directly a POST instead of first a preflight request to ask for permission.
But I still don't know why the filter wasn't able to manage an OPTIONS request and sends by default headers that aren't described in the filter (seems like an override for that only case ... maybe a restEasy thing ...)
So I created an OPTIONS path in my rest service that rewrites the reponse and includes the headers in the response using response header
I'm still looking for the clean way to do it if anybody faced this before.
Apache/HTTPD tends to be around in most enterprises or if you're using Centos/etc at home. So, if you have that around, you can do a proxy very easily to add the necessary CORS headers.
I have a blog post on this here as I suffered with it quite a few times recently. But the important bit is just adding this to your /etc/httpd/conf/httpd.conf file and ensuring you are already doing "Listen 80":
<VirtualHost *:80>
<LocationMatch "/SomePath">
ProxyPass http://target-ip:8080/SomePath
Header add "Access-Control-Allow-Origin" "*"
</LocationMatch>
</VirtualHost>
This ensures that all requests to URLs under your-server-ip:80/SomePath route to http://target-ip:8080/SomePath (the API without CORS support) and that they return with the correct Access-Control-Allow-Origin header to allow them to work with your web-app.
Of course you can change the ports and target the whole server rather than SomePath if you like.
var result=[];
var app = angular.module('app', []);
app.controller('myCtrl', function ($scope, $http) {
var url="";// your request url
var request={};// your request parameters
var headers = {
// 'Authorization': 'Basic ' + btoa(username + ":" + password),
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json; charset=utf-8',
"X-Requested-With": "XMLHttpRequest"
}
$http.post(url, request, {
headers
})
.then(function Success(response) {
result.push(response.data);
$scope.Data = result;
},
function Error(response) {
result.push(response.data);
$scope.Data = result;
console.log(response.statusText + " " + response.status)
});
});
And also add following code in your WebApiConfig file
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
we can enable CORS in the frontend by using the ngResourse module.
But most importantly, we should have this piece of code while making the ajax
request in the controller,
$scope.weatherAPI = $resource(YOUR API,
{callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
$scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if any);
Also, you must add ngResourse CDN in the script part and add as a dependency
in the app module.
<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>
Then use "ngResourse" in the app module dependency section
var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);
I have a Web Api 2 project which I used for a mobile project. I am trying to use the same api's for a web project but am unable to reach them using ajax. I've confirmed that my url is correct and I am able to hit the endpoint from an android project and from fiddler. Am I missing something is my ajax call? I always hit the error function, which returns 'undefined'. I can set a breakpoint in my webapi project and that endpoint is never being hit.
// GET: api/Trips
public IQueryable<Trip> GetTrips()
{
return db.Trips.Include("Users");
}
jquery
$.ajax({
url: 'http://localhost:49669/api/Trips',
type: 'GET',
contentType: 'application/json;charset=utf-8',
success: function (data) {
alert("success!!");
},
error: function (x, y) {
alert(x.response);
}
});
You may need to enable CORS if trying to hit your API form a browser.
Step 1, modify your WebApiConfig file (App_Start/WebApiConfig.cs):
using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Add this line
config.EnableCors();
// the rest of your code
}
}
}
Step 2, add the [EnableCors] attribute to your Web API controller:
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace MyApp.Controllers
{
[EnableCors(origins: "http://www.whatever.net", headers: "*", methods: "*")]
public class HelloWorldController : ApiController
{
// GET: api/Trips
public IQueryable<Trip> GetTrips()
{
return db.Trips.Include("Users");
}
}
}
**Note: ** You may also need to install the CORS nuget package.
Install-Package Microsoft.AspNet.WebApi.Cors
contentType is for the content type beint sent to the server; this is the only possible reason I can imagine your code not working since you said it's never actually making the request so it must be some error handling done by jQuery before making the request, and the error is being thrown because you are trying to specify contentType for a GET request.
The property for specifying a response type is dataType. Try changing contentType to dataType?