Set CORS header in ASP.NET HTTP response - c#

I'm trying to set headers for my HTTP response to include CORS header Access-Control-Allow-Origin in order for the response to be easily read by my Anguler.js web app.
To do that, I'm doing the following:
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace tecboxapi777.Controllers
{
public class WorkersController : ApiController
{
// GET: api/Worker
[Route("api/Workers")]
[HttpGet]
public HttpResponseMessage Get()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
response.Headers.NAME_OF_THE_HEADER = "Access-Control-Allow-Origin";
}
}
}
As you can see, I am unable to find the correct name for the CORS header. I've searched online but all I find is to use something similar to Access-Contro-Allow-Origin = "*" which doesn't even compile.
My question is: How do I properly set my CORS headers so that my Angular.JS webapp is able to read my response?
Currently Firefox's developer mode console returns the following message in whenever I try to do a GET request to my API:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://192.168.0.6:45455/api/Workers. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
Just for the sake of completeness, the Angular.JS code that does the GET request is the following:
posts: Observable<any>;
getPosts(){
this.posts = this.http.get(this.ROOT_URL + '/api/Workers');
console.log(this.posts);
}
EDIT: I accepted Sotiris Koukios-Panopoulos's answer because it's what I did to solve my problem and also it requires no installation of packages. Nevertheless, Manish's answer is the better answer and its the one you should follow if you care about whats considered standard.
It surprises me how everything, even adding headers to a response, requires a package in .NET...

You have two ways to do this.
Enable this using a response header just like you initially tried:
Response.Headers.Add("Access-Control-Allow-Origin", "*");
Configure it globally and use it selectively in your Controllers/Actions.
For this, you can use the guide in the official docs which can explain it more thoroughly than I ever could

Use Microsoft CORS package and install the NuGet package.
Right click on the project -> Manage NuGet Packages...
Install the nuget package Microsoft.AspNet.WebApi.Cors
Then you can configure CORS support for Web API at three levels:
Global level
Controller level
Action level
Example:
Global Level
App_Start/WebApiConfig.cs file
public static void Register(HttpConfiguration config)
{
EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "GET,POST");
config.EnableCors(cors);
}
Controller level
using Microsoft.AspNet.WebApi.Cors
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class TestController : ApiController
{
}
Action level
public class TestController : ApiController
{
[EnableCors(origins: "*", headers: "*", methods: "*")]
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value 1", "value 2" };
}
}
Similarly you could also disable cors for specific actions. Say you have enabled it at controller level but want to disable for few of the actions:
[DisableCors()]
// GET api/values/5
public string Get(int id)
{
return "value";
}

First Install the Microsoft.AspNetCore.Cors Nuget package
Then configure CORS in the ConfigureService method.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => {
options.AddPolicy("AllowMyOrigin",
builder => builder.WithOrigins("http://example.com"));
});
}
Then enable CORS using middleware in the Configure method.
public void Configure(IApplicationBuilder app)
{
app.UseCors("AllowMyOrigin");
}
Enable CORS in .NET Core MVC by enabling it in Controllers or actions or globally
Enable on action method
[EnableCors("AllowMyOrigin")]
[Route("api/Workers")]
[HttpGet]
public HttpResponseMessage Get()
{
// You don't need the following now
// HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
// response.Headers.<NAME OF THE HEADER> = "Access-Control-Allow-Origin"
}
Enable on api controller
[EnableCors("AllowMyOrigin")]
public class WorkersController : ApiController
Enable for the whole application by adding the following in startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<MvcOptions>(options => {
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowMyOrigin"));
});
}

Add below lines of code in your web.config , it will resolve your problem
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST,PUT,DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>

Related

Failed http request WebApi using Angular

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);
// ...
}

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(...)
//...

ASP.NET Core - Swashbuckle not creating swagger.json file

I am having trouble getting the Swashbuckle.AspNetCore (1.0.0) package to generate any output. I read the swagger.json file should be written to '~/swagger/docs/v1'. However, I am not getting any output.
I started with a brand new ASP.NET Core API project. I should mention this is ASP.NET Core 2. The API works, and I am able to retrieve values from the values controller just fine.
My startup class has the configuration exactly as described in this article (Swashbuckle.AspNetCore on GitHub).
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
});
}
else
{
app.UseExceptionHandler();
}
app.UseStatusCodePages();
app.UseMvc();
//throw new Exception();
}
}
You can see the NuGet references...
Again, this is all the default template, but I include the ValuesController for reference...
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
I had the same problem. Check http://localhost:XXXX/swagger/v1/swagger.json. If you get any a errors, fix them.
For example, I had an ambiguous route in a base controller class and I got the error: "Ambiguous HTTP method for action. Actions require an explicit HttpMethod binding for Swagger 2.0.".
If you use base controllers make sure your public methods use the HttpGet/HttpPost/HttpPut/HttpDelete OR Route attributes to avoid ambiguous routes.
Then, also, I had defined both HttpGet("route") AND Route("route") attributes in the same method, which was the last issue for swagger.
I believe you missed these two lines on your Configure:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json", "MyAPI V1");
});
}
To access Swagger UI, the URL should be: http://localhost:XXXX/swagger/
The json can be found at the top of Swagger UI:
If your application is hosted on IIS/IIS Express try the following:
c.SwaggerEndpoint("../swagger/v1/swagger.json", "MyAPI V1");
I was running into a similar, but not exactly the same issue with swagger. Hopefully this helps someone else.
I was using a custom document title and was not changing the folder path in the SwaggerEndPoint to match the document title. If you leave the endpoint pointing to swagger/v1/swagger.json it won't find the json file in the swagger UI.
Example:
services.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("AppAdministration", new Info { Title = "App Administration API", Version = "v1.0" });
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/AppAdministration/swagger.json", "App Administration");
});
#if DEBUG
// For Debug in Kestrel
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Web API V1");
#else
// To deploy on IIS
c.SwaggerEndpoint("/webapi/swagger/v1/swagger.json", "Web API V1");
#endif
When deployed to IIS webapi(base URL) is the Application Alias. You need to keep Application Alias(base URL) same for all IIS deployments because swagger looks for swagger.json at "/swagger/v1/swagger.json" location but wont prefix application Alias(base URL) that is the reason it wont work.
For Example:
localhost/swagger/v1/swagger.json - Couldn't find swagger.json
You must conform to 2 rules:
Decorate all actions with explicit Http Verbs like[HttpGet("xxx")], [HttpPost("xxx")], ... instead of [Route("xxx")].
Decorate public methods in controllers with [NonAction] Attribute.
Note that http://localhost:XXXX/swagger/ page requests for http://localhost:XXXX/swagger/v1/swagger.json file, but an Exception will occur from Swagger if you wouldn't conform above rules.
After watching the answers and checking the recommendations, I end up having no clue what was going wrong.
I literally tried everything. So if you end up in the same situation, understand that the issue might be something else, completely irrelevant from swagger.
In my case was a OData exception.
Here's the procedure:
1) Navigate to the localhost:xxxx/swagger
2) Open Developer tools
3) Click on the error shown in the console and you will see the inner exception that is causing the issue.
I am moving my comment to an answer since it appears to be helpful.
To avoid issues with IIS aliases, remove /swagger/ from the URL path. It should look like this:
app.UseSwaggerUI(c => { c.SwaggerEndpoint("v1/swagger.json", "API name"); });
I don't know if this is useful for someone, but in my case the problem was that the name had different casing.
V1 in the service configuration - V capital letter
v1 in Settings -- v lower case
The only thing I did was to use the same casing and it worked.
If you have any issues in your controller to map to an unique URL you get this error.
The best way to find the cause of issue is exclude all controllers from project. Then try running the app by enabling one controller or one or more methods in a controller at a time to find the controllers/ controller method(S) which have an issue. Or you could get smart and do a binary search logic to find the disable enable multiple controller/methods to find the faulty ones.
Some of the causes is
Having public methods in controller without HTTP method attributes
Having multiple methods with same Http attributes which could map to same api call if you are not using "[action]" based mapping
If you are using versioning make sure you have the method in all the controller versions (if using inheritance even though you use from base)
A common error that we make when use Swagger is to give the same name to(NET ASP) two or more routes. this cause that swagger cannot generate the JSON file. for example, this is a wrong way
[HttpPost, Route("Start")]
public async Task<TransactionResult> WipStart(BodyWipStartDTO data)
{
return await _wipServices.WipStart(data);
}
Other action with the same route name but different action name
[HttpPost, Route("Start")]
public async Task<TransactionResult> WipAbort(BodyWipStartDTO data)
{
return await _wipServices.WipAbort(data);
}
This a correct way
[HttpPost, Route("Start")]
public async Task<TransactionResult> WipStart(BodyWipStartDTO data)
{
return await _wipServices.WipStart(data);
}
[HttpPost, Route("Abort")]
public async Task<TransactionResult> WipAbort(BodyWipStartDTO data)
{
return await _wipServices.WipAbort(data);
}
You actually just need to fix the swagger url by removing the starting backslash just like this :
c.SwaggerEndpoint("swagger/v1/swagger.json", "MyAPI V1");
instead of :
c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
Be aware that in Visual Studio 2022 and .NetCore 6 if you create a new ASP.NET Core Web App, Program.cs has the oposite check for Development environment.
instead of
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
you will find
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
// You shoukd add swagger calls here
app.UseSwagger();
app.UseSwaggerUI();
If you create a new project by selecting the template ASP.NET Core Web API and check "Enable OpenAPI support" you will have different Program.cs with preinstalled swagger package and related code.
This took some time for me to find, hope to help someone.
Adding a relative path worked for me:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("../swagger/v1/swagger.json", "My App");
});
Personally I had the same issue and when I tried again today after a while I found in the new version (2.5.0) that going in the json I could see an explanation of the error that was in here.
Also another thing that helped to fix it to me was removing the hosting information connected to the website that is hold inside "..vs\config\applicationhost.config" at the root of the solution folder
I removed the element that was configuring the website.
<site name="**" id="9">
<application path="/" applicationPool=""></application>
<bindings></bindings>
</site>
I had this problem when I used a inner class in Post parameters
[HttpPost]
public async Task Post([FromBody] Foo value)
{
}
Where Foo is
public class Foo
{
public IEnumerable<Bar> Bars {get;set;}
public class Bar
{
}
}
Try to follow these steps, easy and clean.
Check your console are you getting any error like "Ambiguous HTTP method for action. Actions require an explicit HttpMethod binding for Swagger 2.0."
If YES:
Reason for this error: Swagger expects
each endpoint should have the method (get/post/put/delete)
.
Solution:
Revisit your each and every controller and make sure you have added
expected method.
(or you can just see in console error which controller causing ambiguity)
If NO. Please let us know your issue and solution if you have found any.
Same problem - easy fix for me.
To find the underlying problem I navigated to the actual swagger.json file which gave me the real error
/swagger/v1/swagger.json
The actual error displayed from this Url was
NotSupportedException: Ambiguous HTTP method for action ... Actions require an explicit HttpMethod binding for Swagger/OpenAPI 3.0
The point being
Actions require an explicit HttpMethod
I then decorated my controller methods with [HttpGet]
[Route("GetFlatRows")]
[HttpGet]
public IActionResult GetFlatRows()
{
Problem solved
Make sure you have all the required dependencies, go to the url xxx/swagger/v1/swagger.json you might find that you're missing one or more dependencies.
I was getting this Swagger error when I created Version 2 of my api using version headers instead of url versioning. The workaround was to add [Obsolete] attributes to the Version 1 methods then use SwaggerGeneratorOptions to ignore the obsolete api methods in Startup -> ConfigureServices method.
services.AddSwaggerGen(c =>
{
c.SwaggerGeneratorOptions.IgnoreObsoleteActions = true;
c.SwaggerDoc("v2", new Info { Title = "My API", Version = "v2" });
});
I had the same problem. I was using swagger like below mentioned pattern i.e. "../swagger/v1/swagger.json" because I am using IIS Express.Later than I change it to
"/swagger/v1/swagger.json"and clean,rebuild the solution worked for me.
You might forgetting to include.. StartUp.cs/Configure()
app.UseSwagger();
Check if you forgot to include, you error must be remove.
I'd a similar issue, my Swagger documentation broke after I was adding async version of APIs to existing ones.
I played around the Swagger DLL's by installing / Reinstalling, finally commenting newly added APIs, and it worked.
Then I added different signature in attributes, and bingo!, It worked.
In your case, you are having two API with matching signatures
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{`enter code here`
return "value";
}
Try providing different names in attributes like
[HttpGet("List")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("ListById/{id}")]
public string Get(int id)
{
return "value";
}
This should solve the issue.
I have came across the same issue, and noticed that my API has not hosted in the root folder and in an virtual directory.
I moved my API to the root folder in IIS and worked.
More info in this answer
Take a look on Chrome developer tools, sometimes, swagger.json request throws http 500, witch means that there is some inconsistency on your controllers.
For example: In my case, there is an "Ambiguous HTTP method for action":
Also I had an issue because I was versioning the application in IIS level like below:
If doing this then the configuration at the Configure method should append the version number like below:
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/1.0/swagger/V1/swagger.json", "Static Data Service");
});
I was able to fix and understand my issue when I tried to go to the swagger.json URL location:
https://localhost:XXXXX/swagger/v1/swagger.json
The page will show the error and reason why it is not found.
In my case, I saw that there was a misconfigured XML definition of one of my methods based on the error it returned:
NotSupportedException: HTTP method "GET" & path "api/Values/{id}" overloaded by actions - ...
...
...
In my case problem was in method type, should be HttpPOST but there was HttpGET
Once I changed that, everything starts work.
https://c2n.me/44p7lRd.png
You should install the following packages into your project.
5.0.0-rc4 version of Swashbuckle is the minimum. Otherwise, it won't work.
As of now, directly installing it from Nuget, installs the old versions which won't work for Core 3.
I inserted the following lines into .csproj project file like that:
<PackageReference Include="Microsoft.OpenApi" Version="1.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.0.0-rc4" />
After that, Rebuild installs the newer versions.
If not, you can use restore too.
In the Startup.cs, you should configure Swashbuckle like that:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
services.AddMvc();
}
 
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
//c.RoutePrefix = String.Empty;
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Just go to the "https://localhost:5001/swagger/index.html" and you'll see the Swagger UI.
(5001 is my local port, you should change it with yours)
It took a little time for me to figure it out.
I hope it will help others :)
Answer:
If using directories or application with IIS or a reverse proxy,<br/> set the Swagger endpoint to a relative path using the ./ prefix. For example,<br/> ./swagger/v1/swagger.json. Using /swagger/v1/swagger.json instructs the app to<br/>look for the JSON file at the true root of the URL (plus the route prefix, if used). For example, use http://localhost:<br/><br/><port>/<route_prefix>/swagger/v1/swagger.json instead of http://localhost:<br/><port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json.<br/>
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
app.UseSwaggerUI(c =>
{
//c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
//Add dot in front of swagger path so that it takes relative path in server
c.SwaggerEndpoint("./swagger/v1/swagger.json", "MyAPI V1");
});
}
[Detail description of the swagger integration to web api core 3.0][1]
[1]: https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-3.1&tabs=visual-studio

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