Failed http request WebApi using Angular - c#

I am trying to connect a service created in .net from angular but I get an error with CORS, I have looked for many links but none have helped me since most of the solutions are for .NET CORE and I am using standard .net .
call from angular:
return this.http.post('http://localhost:50112/api/auth', userdata).toPromise();
Api:
public class AuthController : ApiController
{
public async Task<IHttpActionResult> Auth(User userdata)
{
var result = await bllUser.auth(userdata);
return Ok(result);
}
}
and this error:
Access to XMLHttpRequest at 'http://localhost:50461/api/auth' from origin 'http://localhost:4200' 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.
I also tried adding the config.EnableCors statement in my webapiconfig file but it tells me that that statement does not exist
I would appreciate your help, no solution has served me

To use enable cors
Install CORS to the API project "Install-Package Microsoft. Asp. Net. WebApi. Cors".
And change your register method
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("www.example.com", "*", "*");
config.EnableCors(cors);
// ...
}

Related

HTTPClient error when calling ASP.NET Web API REST service from ASP.NET MVC app

I have an ASP.NET MVC application which is invoking a ASP.NET Web Api REST service:
public class MyClass
{
private static HttpClient client = new HttpClient();
public async Task DumpWarehouseDataIntoFile(Warehouse myData, string path, string filename) // See Warehouse class later in this post
{
try
{
//Hosted web API REST Service base url
string Baseurl = "http://XXX.XXX.XX.X:YYYY/";
//using (var client = new HttpClient()) --> I have declared client as an static variable
//{
//Passing service base url
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Serialize parameter to pass to the asp web api rest service
string jsonParam = Newtonsoft.JsonConvert.SerializeObject(myData);
//Sending request to find web api REST service resource using HttpClient
var httpContent = new StringContent(jsonParam, Encoding.UTF8, "application/json");
HttpResponseMessage Res = await client.PostAsync("api/Warehouse/DumpIntoFile", httpContent);
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
// Some other sftuff here
}
//}
}
catch (Exception ex)
{
// Do some stuff here
} // End Try
} // End DumpWarehouseDataIntoFile method
} // End class
The ASP.NET Web API REST Controller:
public class WarehouseController : ApiController
{
public bool DumpIntoFile(string data)
{
// Stuff here
}
}
I have used an HttpClient static variable, I am not enclosing it within a 'using' block because of it is not recommended as explained in this link: YOU'RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
When this code is executed it fails with the error:
System.Net.Http.HttpRequestException: An error occurred while sending
the request. System.Net.WebException: The remote name could not be
resolved: 'xxx'
I think I do not need to dispose HttpClient client object, right?
How can I solve this?
I am using Visual Studio 2013 and NET 4.5 (Not Core)
UPDATE 2020/12/10:
Previous error was occurring because of ASP.NET Web API REST Url was not configured correctly in the internal DNS.
Now after solving previous error I get below one:
404 Not Found
Below some messages of the error returned by client.PostAsync:
Ping to ASP.NET Web API Rest is working.
Maybe it is something missing in my web api routes configuration under App_Start\WebApiConfig.cs below?
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// ConfiguraciĆ³n y servicios de API web
// Rutas de API web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I will assume you're using Web API 2 based on the WebApiConfig that you provided. In regards to the 404 response you're receiving, this stems entirely from the incorrect use of, or lack thereof, routing in your controller actions.
Using your example WebApiConfig, this would enable attribute routing as well as convention-based routing using the default route template for a Web API. The default template will not match according to action name, it only matches according to the controller name and the HTTP method of the request (GET, POST, etc.). Example GET http://localhost:5000/api/books/2 will route to the BooksController and will invoke the action method that matches the naming convention i.e. GetBookById(int id).
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
In your case, you have an action method called DumpIntoFile(string data) which doesn't follow the standard naming convention above, therefore the routing system does not know which action to invoke. You can fix this by using the attribute routing that you enabled in the config. You need to add an attribute to your action method that specifies the HTTP verb as well as the route which should invoke the method. Note the additional attribute that should be added to the controller class, which specifies a route prefix.
[RoutePrefix("api/warehouse")]
public class WarehouseController : ApiController
{
// Routes POST http://localhost:5000/api/warehouse/dump
[Route("dump")]
[HttpPost]
public bool DumpIntoFile(string data)
{
//...
}
}
This will route a POST request to http://localhost:5000/api/warehouse/dump. Obviously the localhost:5000 is a placeholder for whatever your base uri would be. I don't know how complex your data in the request is but you can reference the docs regarding how to deal with the data in your request body. The example is primarily focused on the routing portion.
This is just a quick example, there are various different attributes that you could use to specify the routes, accepted methods and so on. The docs outline it pretty well and provide plenty of examples. Link is provided below. On an additional note, I'd suggest returning one of the IHttpActionResult or HttpResponseMessage types instead of a simple bool/string/int/etc. It just gives you more options for the type of HTTP response that you're returning, these are also in the docs.
Docs: https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
Possible points to look:
Check your WebApi documents. 404 in web API means, either host is not reachable or the endpoint your are calling is wrong. Check that first by pasting the URL in your browser. If its a POST operation and accessible by your machine, then you will get a method not supported error.
If in the browser, if its 404 again but you know its correct then you should look into the ACL (User Authorization and Authentication) of the machine. Whether that machine is reachable/accessible to your network or not.
I can't see any authorization headers in your code. Please check for that as well.
Rarely possible - If it requires some pre-configured app like Facebook, Google etc.

AllowAnyMethod works for some API calls but not for others

I have the form mentioned in this question, but when I submit it I get
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:1113/api/loans. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
and
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:1113/api/loans. (Reason: CORS request did not succeed).
I had fixed this for another API call previously by adding this to me API's Configure in Startup:
app.UseCors(options => options.WithOrigins("*").AllowAnyMethod());
But now for some reason it is blocking the call where the action is
// POST api/loans
[HttpPost]
public void Post(Loan loan)
{
_context.Loans.Add(loan);
_context.SaveChanges();
}
Why?
This is a vague question so I'll give a few tips on what it could be.
First start off by Turning on all Exceptions
There's a chance you're getting an exception before the cors happens so you application
is returning an error response before it can add the cors headers.
.Net-Core require attribute for resolving how to model bind the data. So you're http post method should require either [FromForm] or [FromBody] attributes
[HttpPost]
public void Post([FromForm] Loan loan)
{
_context.Loans.Add(loan);
_context.SaveChanges();
}
Make sure you are actually using you're cors policy. Unless your using an old version of .Net Core you should be implementing your cors policy from the Configure Services method and not the configure method
Try implementing your policy like so:
services.AddCors(options =>
{
options.AddPolicy(DEFAULT_POLICY_NAME, policy =>
{
policy.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
Then in your configure method you just use the policy name
app.UseCors(DEFAULT_POLICY_NAME);
Try using [FromBody]
public void Post([FromBody] Loan loan)
also when you try to send use JSON.stringify instead of modle directly,
this.http.post('http://localhost:1113/api/loans', JSON.stringify(this.model), config).subscribe(data => {
console.log(data);
});

ASP.NET Core Disable CORS for specific controllers

I have different set of controllers in my application (let's say A and B). CORS for A controller needs to be enabled and disabled for B controllers.
I have configured CORS via the policies in the following way:
ConfigureServices method:
services.AddCors(
options =>
{
options.AddPolicy(
"AllowCors",
builder =>
{
builder.AllowAnyOrigin().WithMethods(
HttpMethod.Get.Method,
HttpMethod.Put.Method,
HttpMethod.Post.Method,
HttpMethod.Delete.Method).AllowAnyHeader().WithExposedHeaders("CustomHeader");
});
});
services.AddMvcCore()
Configure method
app.UseCors("AllowCors");
app.UseMvc();
Set of A controllers has EnableCors attribute
[EnableCors("AllowCors")]
public class ControllerA1: Controller
CORS works for set of A controller as expected (tested via the browser). However, it also does work for B controllers! I even tried to disable CORS with DisableCors attribute explicitly:
[DisableCors]
public class ControllerB1: Controller
However, ControllerB1 controller can be requested from UI anyway.
Headers in browser for B1 contoller
Request
Provisional headers are shown
Origin: http://localhost:5000
Referer: http://localhost:5000/all
User-Agent: Mozilla/5.0 AppleWebKit Chrome/69 Safari/537
Response
Request URL: http://XX.XX.XX.XX/getall
Request Method: GET
Status Code: 200 OK
Remote Address: XX.XX.XX.XX:80
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: CustomCount
Content-Type: application/xml; charset=utf-8
Server: Kestrel
Could you please advise how to disable CORS for specific controllers?
In your example, you've done two things of note in setting up the WebHost:
Created a custom CORS policy named AllowCors.
Added the CORS middleware to the pipeline, which uses AllowCors as its policyName.
Here's a snippet of the Invoke function that gets called for the CORS middleware:
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.ContainsKey(CorsConstants.Origin))
{
var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName);
if (corsPolicy != null)
{
var corsResult = _corsService.EvaluatePolicy(context, corsPolicy);
_corsService.ApplyResult(corsResult, context.Response);
...
In this snippet, _policy is null and _corsPolicyName is AllowCors. Because AllowCors is the name of a valid policy that was added using AddCors, this results in the CORS middleware applying the revelant CORS headers for all requests.
In your example, you've also used both [EnableCors(...)] and [DisableCors], which are MVC authorisation filters. By doing this, you're mostly just telling MVC to take care of CORS, which is independent of the CORS middleware you've added to the WebHost's pipeline.
This combination of MVC and CORS middleware is what is causing your unexpected results. The middleware is adding the CORS headers to your request regardless of whether or not you're asking it not to by using the [DisableCors] attribute - the CORS middleware has no idea that this MVC concept (a filter) even exists.
Based on this information, you can fix your issue in one of two ways:
Remove the policyName parameter from your call to UseCors.
Remove the UseCors call itself.
With option 1, the UseCors middleware will use the default policy, if it's been configured using AddDefaultPolicy on the CorsOptions passed into the AddCors delegate.
With option 2, the CORS middleware is simply excluded from the pipeline. This will also work in your example, because you've used [EnableCors(...)] where you need it. This also means that you don't need to use [DisableCors] at all - it'll default to not adding the CORS headers.
This raises the question: When would [DisableCors] be useful? As an example, consider the following basic controller:
[EnableCors("AllowCors")]
public class ExampleController : ControllerBase
{
public IActionResult Action1() =>
...
public IActionResult Action2() =>
...
}
It's clear that in this example, both Action1 and Action2 will set the CORS headers. If you didn't want Action2 to set the headers, you could annotate it with [DisableCors].
The order of the app.useCors is important
//...
app.UseRouting();
app.UseCors("customPolicy");
app.UseEndpoints(...)
//...

Using custom route with versioning in ASP.NET Core 2.0

I use a custom middleware to change the Path used in a request to a WebApi.
In my middleware Invoke, I have:
// code prior to this extracts controller name and remaining path
var newPath = $"/{version}/{controller}/ToDoItemDto/{remainingPath}"; // ToDoItemDto was inserted by me and was not in the original request
context.Request.Path = newPath;
return _next(context);
In my ToDoController, I have:
[Route("api/v{version:apiVersion}/[controller]")]
// other attributes for the controller
public class TodoController : Controller
{
// ...
[HttpGet("TodoItemDto/{primaryId}", Name="GetTodoById")]
public IActionResult GetById(long primaryId)
{
// code here...
}
}
However, when I attempt to access this controller, I get an Http 405 error with the following result:
{"error":{"code":"UnsupportedApiVersion","message":"The HTTP resource that matches the request URI 'http://localhost:1482/v1/todo/ToDoItemDto/1' does not support the API version '1'.","innerError":null}}
I tried adding the following attribute to my GetById() method:
[MapToApiVersion("1.0")]
but that did not help.
I searched the web and found a promising result on the GitHub page for the versioning Api. However, I don't understand the suggested fix (using an IActionResult) in this context.
Can custom route matching be done while also using versioning? If so, how?
You have missed to add api in the route. Try it this way
var newPath = $"api/{version}/{controller}/ToDoItemDto/{remainingPath}";

CORS not working with route

I have an issue with an endpoint on my web api. I have a POST method that is not working due to:
Response to preflight request doesn't pass access control check: 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 405.
I cannot see why that is not working since I have plenty of methods that are working indeed with the same COSR configuration. The only difference is that this method has a specified route, as you can see below:
// POST: api/Clave
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
[Route("{id:int}/clave")]
[HttpPost]
public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros)
{
UsuarioModel usuario = SQL.GetUsuario(id);
if (Hash.CreateMD5(parametros.ViejaClave) != usuario.Clave.ToUpper())
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
else if (Hash.CreateMD5(parametros.ViejaClave) == usuario.Clave.ToUpper())
{
SQL.ModificarClaveUsuario(id, Hash.CreateMD5(parametros.NuevaClave));
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError);
}
}
Any Ideas of why this is happening?.
Thanks!.
Based upon the word "preflight" in your message, this is an OPTIONS verb issue. If you examine the requests and responses, I believe you'll see that the request directly before your POST is an OPTIONS request. The OPTIONS request is asking the server what methods are allowed to be called. If you haven't enabled an OPTIONS response, or your OPTIONS response doesn't include the POST method for that Uri, you'll get this response.
Here's a link describing the concept (see section Preflight CORS Requests)
https://msdn.microsoft.com/en-us/magazine/dn532203.aspx
To account for this bypassing everything OPTIONS is designed to do, you can add code similar to this (don't be a cargo-cult programmer) to a new or existing module's BeginRequest method:
if (context.Request.HttpMethod.ToLower() == "options")
{
var origin = context.Request.Headers["origin"];
context.Response.StatusCode = 200;
context.Response.AddHeader("Access-Control-Allow-Origin", origin);
context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
context.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
context.Response.End();
}
Ideally, though, you would want to programmatically determine whether the request is a valid, and if so, then output a response customized for what is actually allowed.
if you are using web api just create one class at root level name it Startup.cs If you can try adding following code in your startup and see if that works. This code will inject cors middelware in ur application pipeline. You probably need to add owin via nuget. Give it a try
[assembly: OwinStartup(typeof(MyProject.API.Startup))]
namespace MyProject.API
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(WebApiConfig.Register());
}
}
}
Your Web API response is clearly a 405, which indicates that you are calling an URI that does not support your HTTP Method (in this case POST).
Starting from this you need to understand why your URI does not support POST. The most probable answer is that you are calling the wrong URI. The fact that you are getting a CORS error is not the root of your problem and derives from the fact that the wrong URI you are calling does not set any Access-Control-Allow-Origin header.
Looking at your controller method:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
[Route("{id:int}/clave")]
[HttpPost]
public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros)
It appears to me that you are using a Route attribute, but not setting a RoutePrefix attribute in your controller class.
This means that the correct URI for your method is the following one:
http://localhost:xxxx/1/clave
And not, as you might think, that one:
http://localhost:xxxx/api/Clave/1/clave
If you want to access your resource using the second URI you need to put a new RoutePrefix attribute in your Controller:
[RoutePrefix("api/Clave")]
public class ClaveController : ApiController {
//..
}
Hope you are doing good !
you can use below code that will allow origin access on each request response.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", *");}
for more reference you can get help from below link.
http://enable-cors.org/server_aspnet.html

Categories