ASP.NET MVC CORS issue - asp.net

I have an ASP.NET MVC application (.NET 4.6) where on one occasion I need to redirect to a different domain.
So the code is like this (only authenticated users can come to the controller):
public ActionResult UploadForDesign(int parcelId)
{
......
string url = "differentdomain/parcelId" ;
return ReDirect(url);
}
I am getting an error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'.....
Failed to load resource: net::ERR_FAILED
I did the following in the control before redirect call
HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
and I still get the same error.
Also I tried the following in web.config, but didn't help much.
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Now I had another test bare ASP.NET MVC app (.NET 4.5.2) with no authentication, and the above code works fine. I checked all the code and it looks the same except authentication in place and the framework version.
Any idea what to do?

You can try to use the WithOrigins method on your CORS policy and add whatever domain you need:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder =>
.WithOrigins("http://localhost:4200/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
});
Ahhh sorry. I believe you should be able to use something like:
var p = new CorsPolicy();
p.AllowAnyHeader = true;
p.AllowAnyMethod = true;
p.AllowAnyOrigin = false;
p.Origins.Add("http://localhost:4200/");

Related

Acces-Control-Allow-Origin works with Web.config (IIS7) but not with (WebApiConfig.cs) ASP.NET Cross Origin support

For a project i want to load and view a pdf file with angular-pdfjs. The team uses ASP.net Cross Origin, to Allow-Acces-Control, Headers, Credentials etc.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Replace the default implementation of the ITraceWriter with our custom logger.
config.Services.Replace(typeof (ITraceWriter), new GlobalTraceLogger());
// Replace the default exception logger to be able to log exceptions with NLog
config.Services.Replace(typeof (IExceptionLogger), new GlobalExceptionLogger());
// Replace the default exceptionhandler to be able to handle exceptions globally
config.Services.Replace(typeof (IExceptionHandler), new GlobalExceptionHandler());
// We must enable cors, because otherwise we are not able to commuincate with a java script client
// TODO: We need to restirct the requested resource. Do not allow every origin!
// Do not run this in prodocutive environment
var cors = new EnableCorsAttribute("*", "*", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
config.MapHttpAttributeRoutes();
// Make the default return type JSON
var appXmlType =
config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
This works good so far, but if i want to load my pdf file with angular-pdfjs, i get a Cross Origin Error, because Allow-Acces-Control-Origin "*" didn't works for my pdf-url.
(https://img3.picload.org/image/roirrgcw/corsworksnot.png)
But if i using instead of ASP.net Cross Origin Support the Allow-Access-Control of IIS7 in Web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested- With, Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
it works and the pdf will be loaded correctly.
(https://picload.org/image/roirrgci/corsworks.jpg)
But the problem is, at the moment the page is loaded via "file://" and so i get
an error because there is no Access-Control-Allow-Origin for 'null'. That means, my pdf is loading correctly this way, but the login, pictures... won't be loaded anymore. So my question is, if someone knows how i can change the WebApiConfig-Implementation that my pdf-file get an Access-Controll-Allow as well. Or maybe can someone tell where the error could be.
For information:
Thats the way i'm loading the pdf with angular-pdfjs:
<!---------------------------THE PDF VIEWER DIRECTIVE------------------------->
<div pdf-viewer="options" pdf-url="pdfUrl" id="my-viewer" class="col col-lg-10"></div>
<!---------------------------THE PDF VIEWER DIRECTIVE------------------------->
and thats the url, i'm using:
function PdfviewController(ebmGuideLineService, mediaService, $scope, $window) {
var vm = this;
$scope.pdfUrl = 'http://localhost:3787/NCCN_Evidence_Blocks_Melanoma.pdf';
$scope.options = { mouseZoom: false, mousePan: false };
Please tell me, if you need more informations and thank you for your help.

Server application has enabled CORS yet client gets "Access-Control-Allow-Origin" error

I have an RESTful API and I've added this to allow Cross-origin request
public static void Register(HttpConfiguration config)
{
...
// Allow Cross-origin request
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors();
...
}
My client is an AngularJS application calling the server like this
var json = JSON.stringify({
Request: 'INIT'
}),
req = {
method: 'GET',
url: 'http://localhost:51615/api/Call/2/' + json
}
$http(req)
.then(function(response){
console.info('response', response)
})
.catch(function(error){
console.error(error);
})
Even thou Cross-origin should be allowed I still get this error
XMLHttpRequest cannot load
http://localhost:51615/api/Call/2/%7B%22Request%22:%22INIT%22%7D. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:86' is therefore not allowed
access. The response had HTTP status code 400.
How can this be?
Big thanks to #shaunhusain for pointing out that I should take a look at the network response in chrome. Here I saw that the problem was with unsafe data in my url string (the json part). Changing the request from get to post along with json as data and not part of the url fixed my problem
try with putting this two appsettings in web.config of your web api project
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<appSettings>
</configuration>

Hangfire.io Dashboard mapped to IIS Virtual Directory

I'm having trouble getting the Hangfire (1.5.8) dashboard to work inside of an IIS Virtual Directoy. Everything works beautifully in my dev environment where my application is simply mapped to the root of localhost. Our beta server, on the other hand, uses Virtual Directories to separate apps and app pools.
It's an ASP.Net MVC site using Hangfire with an OWIN Startup class. It gets deployed to http://beta-server/app-name/. When I attempt to access either http://beta-server/app-name/hangfire or http//beta-server/hangfire I get a 404 from IIS.
For the purposes of troubleshooting this, my IAuthenticationFilter simply returns true.
Here is my Startup.cs, pretty basic:
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
GlobalConfiguration.Configuration
.UseSqlServerStorage(new DetectsEnvironment().GetEnvironment());
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AuthorizationFilters = new[] {new AuthenticationFilter()}
});
app.UseHangfireServer();
}
}
Does anyone have a working implementation that gets deployed to a Virtual Directory? Are there any OWIN middleware admin/management tools I can use to dig into what URL is getting registered within IIS?
I ended up fixing this simply by adding the HTTPHandler to the section in web.config.
<system.webServer>
<handlers>
<add name="hangfireDashboard" path="hangfire" type="System.Web.DefaultHttpHandler" verb="*" />
</handlers>
</system.webServer>
I had a similar issue in ASP.NET Core 2.0 and it required proper authorization setup (I use a middleware to protect the route, so I did not rely on authorization in my example):
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new [] {new HangfireDashboardAuthorizationFilter()}
});
/// <summary>
/// authorization required when deployed
/// </summary>
public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter
{
///<inheritdoc/>
public bool Authorize(DashboardContext context)
{
// var httpContext = context.GetHttpContext();
// Allow all authenticated users to see the Dashboard (potentially dangerous).
// handled through middleware
return true; // httpContext.User.Identity.IsAuthenticated;
}
}
There is not need to change anything in web.config.
For more information check Hangfire documentation about this topic.
I had the exact same problem. In my case, this was because of bad configuration - the Startup class was not called. So try to add the following to your config file:
<add key="owin:appStartup" value="YourProject.YourNamespace.Startup, YourProject" />
<add key="owin:AutomaticAppStartup" value="true" />
Hope this helps.
Martin

ASP.NET MVC5 Customised Inbound Routing

I'm "playing" around with custom inbound URL routing and have came across a problem.
When I pass my custom route a URL to examine, that ends in *.+, my class is not fired when i submit the request.
An example URL would be "~/old/windows.html"
When I step through this in the debugger, my RouteBase implementation doesn't fire. If i edit the url that i pass to the constructor of my route to try to match against "~/old/windows", my implemetation is fired as expected.
Again, If i change the url ro examine to "~/old/windows." the problem reoccurs.
My Route Implementation is below :-
public class LegacyRoute : RouteBase
{
private string[] _urls;
public LegacyRoute(string[] targetUrls)
{
_urls = targetUrls;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (_urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase))
{
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action","GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
In the RoutesConfig file I have registered my route like so :-
routes.MapMvcAttributeRoutes();
routes.Add(new LegacyRoute(new[]{"~/articles/windows.html","~/old/.Net_1.0_Class_Library"}));
Can anyone point out why there is a problem?
By default, the .html extension is not handled by .NET, it is handled by IIS directly. You can override by adding the following section in Web.config under <system.webServer> -
<handlers>
<add name="HtmlFileHandler" path="*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
As pointed out here. The above will route EVERY .html file request to .NET, you might want to be more specific by providing a more complete path if you don't want your routing to handle every .html file.
I've found the problem, and I'm sure this will help out a lot of fellow developers.
The problem is with IIS Express that is running via Visual Studio.
There is a module configured in the applicationhost.config called :-
UrlRoutingModule-4.0
This is how it looks in file :-
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
You need to set the preCondition Parameter to "".
To do this :-
Run you app via Visual Studio
Right click on IIS Express in your system tray, select "Show All Applications"
Click on the project you wish to edit, then click the config URL.
Open the file with Visual Studio, Locate the module and ammend.
Hope this helps anyone else, who ran into a similar problem.

How to use cross-domain connections (CORS - Access Control Allow Origin) with SignalR

Using persistent connections and an ASP.NET JavaScript client, I am trying to connect to a sub-domain not the same as the one the page was served from.
ASP.Net Page from webserver sub1.mydomain.com wants to connect to SignalR at sub2.mydomain.com. The same code works fine when connecting within the same sub-domain.
I found another post where cross-domain connections were enabled with:
jQuery.support.cors = true;
but this did not work for me.
How can I connect to SignalR in a second sub-domain using persistent connection and a JavaScript client?
You need to do one of the following to make it work:
Set up $.connection.hub.url = 'http://subdomain.domain.com/signalr';, pointing to your subdomain.
Enable cross domain on the server:
RouteTable.Routes.MapHubs(new HubConfiguration()
{
EnableCrossDomain = true
});
In the current version of SignalR, using the now separate CORS package, the API for this has changed to:
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
};
map.RunSignalR(hubConfiguration);
});
}
See ASP.NET SignalR Hubs API Guide - JavaScript Client.
If switching from 0.5.1 to 0.5.2, you may have had the following:
$.connection.hub.start({ transport: 'longPolling', xdomain: true }, function () {...
Which can be changed to:
$.connection.hub.start({ jsonp: true }, function () {...
In Signalr2, you can use the pre-release of Microsoft.Owin.Cors, currently 3.0.0-rc1 as of writing this: Microsoft.Owin.Cors.
More information can be found here:
http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-javascript-client
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20
var connection = $.connection('http://somecrossdomainurl/echo')
connection.start({ transport: 'longPolling', xdomain: true });
https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client
What really have solved my issue was:
1 - Add this to global.asax:
RouteTable.Routes.MapHubs(new HubConfiguration() {
EnableCrossDomain = true
});
2- Set up the web.config of my web project to enable the cross-domain:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
3- Then I change the implementation on my html, changing the $.connection() to as follow:
var connection = $.hubConnection('http://localhost.my:8081/signalr');
var chatHubProxy = connection.createHubProxy('chatHub');
Versions I'm using:
signalR-1.1.0
jquery.signalR-1.1.3.js
dot.net 4.0

Resources