I have a web api in asp.net 4.5. I have installed nuget package for cors
and made corresponding code changes
in WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
In the controller
[EnableCors(origins: "http://localhost:56241/api/loancopy/3219795539", headers: "*", methods: "*")]
[RoutePrefix("api/loancopy")]
public class MainController : ApiController
{
[HttpPost]
[Route("{loannumber}")]
public HttpResponseMessage PostLoanCopy([FromUri]string loanNumber, [FromBody] LoanDto LoanDto)
{
return new HttpResponseMessage();
}
}
This is my client side post request in angular2
export class HeroService {
private heroesUrl = 'http://localhost:56241/api/loancopy/3219795539';
private body = 'body'
constructor(private http: Http) { }
addHero(name: Loan): Observable<Loan> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.heroesUrl, JSON.stringify(Loan), options)
.map(this.extractData)
.catch(this.handleError);
}
My client says Response for preflight has invalid HTTP status code 500
Looking at your code I presume you followed this documentation
I'm finding it strange that the URL your client calls is exactly the same as the url declared as acceptable origins:
Angular2:
private heroesUrl = 'http://localhost:56241/api/loancopy/3219795539';
WebApiConfig.cs
[EnableCors(origins: "http://localhost:56241/api/loancopy/3219795539", ...
The origins parameter is used to indicate from which hosts do you accept incomming requests, and the value you seem to be using is the exact same host as the .net application is running. Consider changing it to the host you are accessing your angular2aplication.
For example, if you are running it in localhost, on port 3000, the EnableCors declaration should be the following:
[EnableCors(origins: "http://localhost:3000", headers: "*", methods: "*")]
Also, as #Developer noted, the origin declaration should not contain the path, just the host.
So use something like origins: http://localhost:3000 instead of http://localhost:3000/path/to/angular/page
Related
I have a react app calling my service with CORS enabled from my local app. This works fine for GET methods but for some reason it throws a CORS exception when calling a POST method. Is there anything I need to add to configure for POST? thanks
in my startup.cs:
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins(
"http://localhost:3000"
);
});
});
In my react app the call is pretty basic:
axios({
method: "POST",
url: `https://localhost:44340/patientsearch`,
data: { searchModel },
});
The exception:
Access to XMLHttpRequest at 'https://localhost:44340/patientsearch' from origin 'http://localhost:3000' 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.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(x =>
{
x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithOrigins("https://localhost:5002");
});
}
My asp.net owin api has the following middleware to define the oauth2 tken endpoint.
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = _env.IsDevelopment,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(24*60),
Provider = _oAuthAuthorizationServerProvider,
AccessTokenFormat = new CustomJwtFormat(_issuer, _secret)
});
When trying to log through my web app, the http post request happens after a http options preflight request that the browser initiates.
However, the options request failed with error message "unsupported_grant_type" as this preflight request initiated by the browser has no body.
As per that post, the solution is to override MatchEndpoint in our derived class of OAuthAuthorizationServerProvider:
public override Task MatchEndpoint(OAuthMatchEndpointContext context)
{
if (context.OwinContext.Request.Method == "OPTIONS" && context.IsTokenEndpoint)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "accept", "authorization", "content-type" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
context.OwinContext.Response.StatusCode = 200;
context.RequestCompleted();
return Task.FromResult<object>(null);
}
return base.MatchEndpoint(context);
}
Having issues when sending a POST request via my Angular 2 service to an ASP.NET Core API. I am currently getting a HTTP 500 error:
"XMLHttpRequest cannot load http://localhost:51014/api/sites. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500."
I am not getting this error on GET requests and as far as I can see I have CORS setup correctly server side?
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors();
services.AddMvc();
....
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseCors(builder =>
builder.WithOrigins("http://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod());
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
SitesContoller.cs
// POST: api/Sites
[HttpPost]
public async Task<IActionResult> PostSite([FromBody] Site site)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Sites.Add(site);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (SiteExists(site.Id))
{
return new StatusCodeResult(StatusCodes.Status409Conflict);
}
else
{
throw;
}
}
return CreatedAtAction("GetSite", new { id = site.Id }, site);
}
My Angular 2 service:
site.service.ts snippet
public createSite(site: Site): Observable<Site> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(site);
return this.http
.post(this.apiUrl + 'sites', { body }, options)
.map((res: Response) => res.json());
}
You need to add the EnableCors attribute to your SiteController class. Like this
[EnableCors(origins: "http://<SOME_SITE>", headers: "*", methods: "*")]
public class SiteController {
.....
}
refer to this link
Cannot tell from you code snippet this is the case, bit you do need it.
I am trying to use post method of Web API from angularjs code but the data that I am sending from $http is not reaching to Web API method. The planDetailsVM parameter remains null. Below is my code-
Web API Controller code-
public class RateCalculationController : ApiController
{
[HttpPost]
public RateCalcOutParmDTO GetPlanRateCalculation(PlanDetailsVM planDetailsVM)
{
//planDetailsVM remains null
RateCalcOutParmDTO rateCalcOutParmDTO = new RateCalcOutParmDTO();
// Some operation here
return rateCalcOutParmDTO;
}
}
Here planDetailsVM remains null.
AngularJs Code-
$http({
url: key_Url_GetPlanRateCalculation,
method: 'Post',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
params: $scope.PlanDetails
}).then(function (result) {
//Some operation here
});
Route mapping code-
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
I tried to follow one of the solution at this link AngularJs $http.post() does not send data but it's not working for me. What can I need to do so that planDetailsVM receives the posted data from AngularJS http post?
PlanDetails data-
$scope.PlanDetails = { QuoteName: null, BenefitAmountId: 0, BenefitAmountValue: null, DoD_Id: 0, DoD_Value: null, EPBD_Id: null, EPBD_Value: null, _DisplayMsg: null, _DisplayFlag: false };
I was able to solve this issue by just replacing key "params:" with "data:" in the https post request as suggested by Ben. Below is the angularJS code that did the work-
$http({
url: key_Url_GetPlanRateCalculation,
method: 'Post',
data: $scope.PlanDetails
}).then(function (result) {
//Some operation here
});
I am working with asp.net MVC 4.0,In my API Controller I am having two save methods which are called through AJAX calls.The issue is both of them are not working simultaneously i.e the method doesn't get called.
If i comment one the other works fine
Sample Code of APIController:
[HttpPost]
public IEnumerable<Model1> Save1 (Model1 model1)
{
//code
}
[HttpPost]
public IEnumerable<Model2> Save2(Model2 model2)
{
}
Code of json :
$.ajax
({
url: "/api/Myapi/Save1",
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(model1),
success: function (data) {
alert("success");
return true;
}
});
similar code for Save2 Method
Please suggest.
If you want to violate the standard RESTful routing convention and use custom names for your actions you will have to define a custom route in your WebApiConfig containing the {action} part in it:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
The RESTful routing convention dictates that you should have a single action per HTTP verb and per resource (i.e API controller).