Cors Error - MVC and Web API - asp.net-mvc-4

I have an MVC application which also uses webapi2.
To call the api services i am using jquery ajax as below.
$.ajax({
url: GetBaseURL() + '/api/MyController/PutMethod',
type: 'put',
data: dataObject,
contentType: 'application/json',
timeout: AJAX_TIMEOUT,
success: function () {
self.CallOtherFunction();
});
And the function getbaseURL returns content.url("~")
While this approach is working out from some pages, it's throwing the "Cross Origin Request Blocked : The same origin policy disallows reading the remote resource at http://api/MyController/PutMethod" error.
I have tried googling out on cors but could not understand why I am facing this error, even though I have both MVC and Webapi under one solution, running through visual studio.
Help appreciated.
Thanks.

The problem is in your WebApi. The projects could be in the same solution and only the port could be different and you would get the CORS error. To solve the WebApi problem you can read this article: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

if you facing this error while calling of an api in mvc then you follow the below steps
Step 1 :put this tags in your web.config file in api under the system.webServer tag.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, X-Your-Extra-Header-Key"/>
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS"/>
<add name="Access-Control-Allow-Credentials" value="true"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Step 2- put this in gloabl.asax.cs file in your webapi application
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
Response.Flush();
}
}

Related

Filepond http uploading files IIS server setup problem 405

I'm trying to get a uploading script running, filepond, uploading files through webpage. On IIS10, on co-located server.
When uploading, using POST, I get the following error:
HTTP Error 405.0 - Method Not Allowed
The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.
in details:
Module DirectoryListingModule
Notification ExecuteRequestHandler
Handler StaticFile
Error Code 0x80070001
Requested URL https://www.example.com:443/upl/files/
Physical Path W:\www.example.com\www\upl\files\
Logon Method Anonymous
Logon User Anonymous
Request Tracing Directory C:\inetpub\logs\FailedReqLogFiles
port 443 is open.
The folder has the following web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
</system.webServer>
</configuration>
The folder has the following attributes:
IIS > site > folder > configuration Editor > system.webServer/handlers
FROM SITE/upl/files Web.config > accesPolicy: Read, Write, Execute, Script
FROM SITE/upl Web.config > accesPolicy: Read, Execute, Script (no solution when adding "Write")
FROM ApplicationHost.config accesPolicy: "Read, Execute, Script"
Athentication: Anonymous Athentication status enabled, rest disabled
Handler Mappings > Static File
Path: *, State: enabled,
PathType: File or Folder,
Handler: StaticFileModule,DefaultDocumentModule,DirectoryListingModule,
Entry Type: Local
EDIT > Request Restrictions > Mapping : selected Invoke handler only if request is mapped to File or folder, Verbs: GET,HEAD,POST,DEBUG,
Access: Write ( I dont understant why there is no Read/Write option, only read / write / script / execute )
Properties > security >
even when giving full control on that folder to Everyone + IUSR + IIS_IUSRS + Users : still same error.
I did notice in Handler Mappings there is no *.js record.
In Handler Mappings changing the *.asp > edit > "file" to "file and folder" had no effect either.
Jic: I could not find Filepond using a temp folder that I forgot to give acces rights to.
Jic; these are my present FilePond server settings:
FilePond.setOptions({
server: {
url: 'https://www.example.com/upl/',
timeout: 3000,
process: {
url: 'files/',
method: 'POST',
headers: {
'x-customheader': 'Hello World',
},
withCredentials: false,
onload: (response) => response.key,
onerror: (response) => response.data,
ondata: (formData) => {
formData.append('Hello', 'World');
return formData;
},
},
revert: './revert',
restore: './restore/',
load: './load/',
fetch: './fetch/',
}
});
I looked at all the previous answers here and elsewhere for over a day now, but seem to miss a tiny vital thing. Any help is very much appreciated !!
Alex
------------ replying to Samwu:
Thank you for helping.
The above represents most of the solutions I looked at.
I followed the link, found this earlier and here are some findings:
the client makes a Hypertext Transfer Protocol (HTTP) request by using an HTTP method that doesn't comply with the HTTP specifications.
In the ApplicationHost.config file, Make sure that all the handlers use valid HTTP methods.
from my applicationHost.config:
<handlers accessPolicy="Read, Execute, Script">
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" />
<add name="StaticFile" path="*" verb="GET,POST" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
<sectionGroup name="webdav">
<section name="globalSettings" overrideModeDefault="Deny" />
<section name="authoring" overrideModeDefault="Deny" />
<section name="authoringRules" overrideModeDefault="Deny" />
</sectionGroup>
all the modules are stated in applicationHost.config modules
I did notice however something: in the www root there is a web.config that says:
<remove name="ASPClassic" />
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Script" />
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Either" requireAccess="Script" />
</handlers>
in the upl / files / dir there is a webconfig saying:
<system.webServer>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
</system.webServer>
notice the " requireAccess="Script" instead of Write
"Send the POST request to a page that's configured to be handled by a handler other than the StaticFile handler. For example, the ASPClassic handler. "
I assume that if my filepond js module is included in a .asp page that this is what I am all ready doing.
WebDav is not installed, it is still stated in the applicationHost.config. Removing that gives an error on restarting the site in IIS.
I hope that clearifies.

How can I enable cors when using signalR in asp.net mvc?

I use signalR in asp.net mvc for web api and I need to enable cors in web.config.
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true"/>
<add name="Access-Control-Allow-Headers" value="X-Requested-With, origin, content-type, accept" />
But when I'm going to connect to signalR, it displays the following error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include
Follows the code to the startup.cs:
[EnableCors("CorsPolicy")]
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
How can I fix it?
As your error says:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'.
And you have:
<add name="Access-Control-Allow-Origin" value="*" />
So in this case you should provide the origin from where you are connecting. If you are trying to connect from the front-end you can use this as an example:
<add name="Access-Control-Allow-Origin" value="https://localhost:4200"/>

Enable CORS in Azure web

What I´m trying to do is to enable CORS (Cross-origin Resource Sharing) for .net MVC 5 Azure website when calling a https service (not my own) from my JavaScript.
I always get the same error
XMLHttpRequest cannot load https://someservice-I-have-no-control-over. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://my.azurewebsites.net' is therefore not allowed access. The response had HTTP status code 400.
I have managed to enable this when developing locally, setting my project to https and adding the following to web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, SOAPAction"/>
<add name="Access-Control-Max-Age" value="1728000"/>
</customHeaders>
</httpProtocol>
</system.webServer>
That adds the 'Access-Control-Allow-Origin' header. But that does not seem to work on the Azure website.
And I can´t find any settings like in the Mobile Services where you can allow this like you see here.
Since I know you are all going to ask for code (that works locally btw) there you have the simple Jquery call to the service
$.ajax({
url: 'https://someservice-I-have-no-control-over',
dataType: 'json',
contentType: 'application/json',
type: 'GET',
success: function (response) {
$.each(response, function (key, value) {
console.log("success"); //Doesn´t happen! :-(
});
},
error: function (xhr, text, error) {
if ($.isFunction(onError)) {
onError(xhr.responseJSON);
}
}
});
So any thoughts?
Edit 1
Just to clarify a little.
I am calling a service that I have no control over that is a https one, in a javascript (not a controller) that is mine.
Edit 2
Ok I thought that I could intercept the response from the third party service and add this header before the browser rejects it. As I see it that is not possible (right?). But how come it works locally?
If I capture the call to this service with e.g LiveHTTPHeaders I get the following response where there is not a "Access-Control-Allow-Origin" restriction (so way does it work locally?).
Request (to https://someservice-I-have-no-control-over.com)
GET /someservice-I-have-no-control-over/SomeAction/44 HTTP/1.1
Host: someservice-I-have-no-control-over.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
If-None-Match: "53867cff-96b0-411f-88b7-d84765f9f8e8"
Cache-Control: max-age=0
Reply
HTTP/1.1 304 Not Modified
Cache-Control: max-age=900
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Date: Tue, 24 Feb 2015 11:06:53 GMT
Not possible.
It works locally because it's the server that must have the allow headers, and when you call your own webserver from your javascript you can add those headers.
When you call the real website they do probably not add the CORS allow header (Access-Control-Allow-Origin) and your request is therefore denied.
What you could do is either to use JSONP or proxy all requests through your own website.
You could for instance use my CORS proxy: https://github.com/jgauffin/corsproxy. It's intended usage is for IE9 and below, but works just as fine for all requests.
WebApiConfig I set it the WebApiConfig class and it worked. I also had issues on Azurewebsites when trying to set it via web.config.
Try this in WebApiConfig:
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
You can edit the "", "", "*" if you don't want to allow everything.
If you're using Owin, you can do this in the Startup.cs file:
app.UseCors(CorsOptions.AllowAll);
Use this if and only if you intentionally plan to expose your API to all origins and headers.
Else, you can try it this way by decorating your controller or specific methods:
[EnableCors(origins: "http://someCallingService", headers: "*", methods: "*")]
Check out THIS article
I addressed this by installing the following package:
Microsoft.AspNet.WebApi.Cors
...then using the Config.EnableCors() as described above and altering my web.config transform:
In WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Continue configuration as you wish...
}
Then, in the web.config transform, in my case named web.PPE.config because it's for Pre-Production:
<system.webServer>
<httpProtocol>
<!-- custom headers necessary for CORS -->
<customHeaders xdt:Transform="Replace">
<clear /> <!-- the clear here is important! -->
<add name="Access-Control-Allow-Origin" value="http://url-that-is-allowed-to-communicate-with-this-server.com" />
<!-- must match server DNS address or SignalR can't communicate with Hub remotely -->
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
</system.webServer>
YMMV on whether to include the Allow-Credentials option. I found that necessary with my need, which was to enable access to a SignalR hub on a remote Azure webserver/app instance.
Good luck!

asp.net MVC 4 + WebAPI hosted in IIS 7.5 with windows authentication gives 401 unauthorized error

I've hosted asp.net MVC 4 + WebAPI in IIS 7.5 with windows authentication. When I call the WebAPI from MVC4 view, it gives me 401 unauthorized error. But it works perfectly fine from my localhost.
I've set the principal in both the places (Thread.CurrentPrincipal & HttpContext.Current.User) from my AuthenticationModule class.
I tried with System.Web.HTTP AuthorizeAttribute.
When I debug with Jquery console, i could see the context principal is null.
Let me know the following.
IIS hosting configuration?
How to design the WebAPI authenticate/authorize calls from views?
Could you show me how are you calling the web api? If you are calling it with an
httpclient you should provide a handler. I show you below:
var handler = new HttpClientHandler()
{
UseDefaultCredentials = true
};
var client = new HttpClient(handler);
Something wrong in my handler registration; I forgot to add it under system.webServer;
Actual configuration:
<configuration>
<system.web>
<httpModules>
<add .........../>
</httpModules>
</system.web>
</configuration
Added configuration:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add .........../>
</modules>
</system.webServer>
</configuration

StarterSTS FederationMetadata Generator configuration for asp.net mvc 4

How do i configure dynamic federation metadata generator http handler that comes with StarterSTS to work along with ASP.NET MVC 4, right now i got this configuration inside web.config on IIS 7 but browser returns 404 not found
<!-- handler to dynamically generate WS-Federation metadata -->
<location path="FederationMetadata/2007-06">
<system.webServer>
<handlers>
<add name="MetadataGenerator" path="FederationMetadata.xml" verb="GET" type="Thinktecture.IdentityServer.WSFedMetadataGenerator,Thinktecture" />
</handlers>
</system.webServer>
<system.web>
<httpHandlers>
<add path="FederationMetadata.xml" verb="GET" type="Thinktecture.IdentityServer.WSFedMetadataGenerator,Thinktecture" />
</httpHandlers>
</system.web>
</location>
404 Not found
https://localhost/website/FederationMetadata/2007-06/
Ok here is the truth it does not work. So here is what i did,
created a new asp.net mvc controller named it FederationMetadata
Copied the code to generate the federation metadata in the Index action method
Always point to https://<pc:name>/stsvirtualdirectoryname/FederationMetadata/ to get the federation metadata xml document
Code
if (STS.Configuration.Endpoints.WSFedMex)
{
EnsureInitialized();
var serializer = new MetadataSerializer();
var sb = new StringBuilder(512);
serializer.WriteMetadata(XmlWriter.Create(new StringWriter(sb),new XmlWriterSettings { OmitXmlDeclaration = true }), _entity);
return new ContentResult(){Content = sb.ToString(),ContentEncoding = Encoding.UTF8,ContentType = "text/xml"};
}
else
{
throw new HttpException(404, "Not found");
}