AJAX Cross Domain Image Post to WCF Service - ajax

I've been stuck for 2 days on this.
Can someone please provide an example of how to do a cross domain AJAX post to a WCF service?
I'm trying to upload an image to the WCF server.
EDIT
WCF Service:
[WebInvoke(UriTemplate = "/upload", Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped), CorsEnabled]
void UploadImage(Stream image);
Ajax Call:
function UploadImage() {
image = document.getElementById("myimage").src;
var data = '{"image": "' + image + '"}'
//alert(data);
$.ajax({
url: "http://localhost:44665/api/upload",
type: "POST",
contentType: "application/json",
data: data,
success: function (result) {
alert("success");
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.responseText);
}
});
}
I can get this to work if I change the WCF paramter from Stream to string. But I need to upload an image and not a string.
I am now getting a WCF error that says:
The server encountered an error processing the request. See server logs for more details.
** Edit 2 **
I added the global.asax code mentioned in the below answer and added this to my web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<servicedebug includeexceptiondetailinfaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
</configuration>
I now get an error in the Google Chrome console that says:
POST http://localhost:44665/api/upload 500 (Internal Server Error)

So you are trying to make a POST operation from JavaScript to a WCF service that is hosted in another domain. Normally you can't do that without doing some special settings in the WCF service side.
You have to add the following headers to the response from Global.asax.cs in the service side (If the service project doesn't contains Global.asax.cs create one).
protected void Application_BeginRequest(object sender, EventArgs e)
{
//..
EnableCrossDomainCall();
}
private void EnableCrossDomainCall()
{
// this header tells that from any domain you can access me.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
// this one tells about the supported methods to client.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
"GET, POST, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
"Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
UPDATE:
You can't just post any file through AJAX, through AJAX you can only transfer data. You can use this plugin that uses hidden iframe to upload files that imitates like AJAX.
You can handle the stream object in WCF side as in this link. Try uploading small size images first and you can control the maximum size by setting the maxRequestLength in web.config.

I had this problem and tried the code did not work.
I changed the code and started to work.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST,OPTIONS");
if ((HttpContext.Current.Request.HttpMethod == "OPTIONS"))
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}

Related

Error facing on communication between asp.net webapi server and angular2 application

I am facing the CORS related issue when i try to connect my angular2 application and asp.net webapi application.
Error:-
register:1 Access to XMLHttpRequest at 'http://localhost:49457/api/UserDetails' from origin 'http://localhost:4200' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:4200, http://localhost:4200', but only one is allowed.
Here is my code for connecting for calling asp.net webapi url through my angular2 app:-
User.service.ts
GetUser(userobj:user):Observable<User>
{
return this.http.get<User>(`http://localhost:49457/api/UserDetails`,{responseType:"text"})
.subscribe(
function(response)
{
console.log("user details retreived successfully");
},
function(error)
{
console.log(error);
});
}
This is my code for asp.net webapi,
public class UserDetailsController : ApiController
{
private sampledbEntities dbentity = new sampledbEntities();
// GET api/<controller>
public IQueryable<Userdetail> GetUserdetails()
{
return dbentity.userdetails;
}
}
Actually when i run my asp.netwebapi server it is retrieving data correctly through browser.And also i have enabled
CORS in webapiconfig.cs,
void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("http://localhost:4200", "*", "*");
config.EnableCors(corsAttr);
}
in web.config.cs,
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Headers" value="Origin, Content-Type, X-Auth-Token" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
After enabling CORS in Webapiconfig.cs and web.config also i am facing the same error.
Please clarify how do i come out of this error,
Replace http://localhost:4200 with "*" from EnableCorsAttribute method.
void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("http://localhost:4200", "*", "*");
config.EnableCors(corsAttr);
}
and remove httpProtocol configuration settings from web.config.

No custom/authorization Headers in MVC 5 controller

I have an MVC 5 ViewController which does not accept headers from an Ajax call. The ajax call origin is a different website then the controller.
The Ajax call looks like:
window.jQuery.ajax({
url: 'http://localhost:54155/TestView',
headers: {'Authorization': 'token'},
cache: false,
contentType: 'application/json; charset=utf-8',
method: 'Get',
dataType: 'json',
data: {}
}).success(alert('succes?'))
.error(alert('failed'))
});
Cors is enabled on the controller side:
<httpProtocol>
<customHeaders>
<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>
And I'm trying to reach this controller:
public class TestViewController : Controller
{
public ActionResult Index()
{
var keys = Request.Headers.AllKeys;
return View();
}
}
If I send the request to a WebApi based on a WEP API 2 controller, the headers are ok. If I send a request with postman to the mvc controller the headers are ok as well.
The Headers contain the header Access-Control-Request-Headers, which has the value authorization. But Request.Headers["Authorization"] is null.
Custom headers like X-MyHeader turn up as value from Access-Control-Request-Headers, but when used like a key, they are all null.
Which part am I missing?
I had a same kind of issue - but this might resolve your problem
Install Microsoft.AspNet.WebApi.Cors from NuGet - Run this command
(Install-Package Microsoft.AspNet.WebApi.Cors) in your package
manager console - this will install your Cors
Remove your access allow origin code from your Web.config file
If it is Web Api add the below cod in your WebApiConfig.cs if not try to add in your Gloabl.asax
var cors = new EnableCorsAttribute("*", "*", "*", "*");
config.EnableCors(cors);
You will be wondering where that method EnableCors() will come using System.Web.Http.Cors; add this line in your using and see the magic
This might solve your problem - Finally its not a good idea to access your MVC controller from different domain try you use WebApi
If you want to access your MVC controller try out your ajax code form the same domain
Because WebApi is stateless but MVC is kind of session - Thanks happy coding !!

500 System.ServiceModel.ServiceActivationException when making an Ajax call to WCF rest service

Ajax Call:
$.ajax({
type: "POST",
url: "http://SomeService/ServiceName.svc/GetSearchResults",
data: JSON.stringify({ parameters: serviceParameters }),
contentType: "application/json; charset=utf-8",
dataType: "XML",
success: function (response) {
$("#xmlText").text(response.xml);
},
error: function (msg) {
alert(msg.toString);
}
})
WCF Interface:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Json,
UriTemplate = "GetSearchResults")]
XElement GetSearchResults(inputParameters parameters);
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "getFile")]
Stream GetFile(DocInfo info);
Web.config:
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
</serviceHostingEnvironment>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"></standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
The service is hosted on IIS6.
When I call the service I get the following error message:
500 System.ServiceModel.ServiceActivationException
I can call the GetFile method and get the response stream but I get the error message when calling GetSearchResults.
Any help will be appreciated.
I encountered this error for the reason mentioned below
Memory gates checking failed because the free memory (258187264 bytes) is less than 5% of total memory. As a result, the service will not be available for incoming requests. To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.
Many thanks for your inspired replies and comments.
I actually encountered the same error but with different story:
At first, I got "404 (Not Found)" server error, which is because I did not have a transport for "HTTPS" as well as I already have one for the "HTTP".
I added a <httpsTransport> to my <binding> element, so it looked like this:
<bindings>
<customBinding>
<binding name="CustomBinding_ITheService">
<httpTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
<httpsTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
</customBinding>
</bindings>
Then I got the 500 System.ServiceModel.ServiceActivationException error. However, I navigated "Event Viewer > Windows Log > Application" and found that "transports cannot be defined more than a time for the same binding". So, I decided to add an additional endpoint with a new binding for the "HTTPS" transport.
At the end, my configuration looks like the following:
<services>
<service name="TheService" behaviorConfiguration="WebHttpBehavior_ITheService">
<endpoint binding="customBinding" bindingConfiguration="CustomBinding_ITheService" contract="ITheService" behaviorConfiguration="EndPointBehavior_ITheService" />
<endpoint binding="customBinding" bindingConfiguration="CustomBinding_ITheService_Secured" contract="ITheService" behaviorConfiguration="EndPointBehavior_ITheService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="CustomBinding_ITheService">
<httpTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
<binding name="CustomBinding_ITheService_Secured">
<httpsTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
</customBinding>
</bindings>
Then every things goes the right way and works perfectly.
In case you develop on visual Studio and use IIS-Express "Cassini", remember to enable SSL option in the properties of the website-project, that tells IIS-Express to prepare a base URL for the HTTPS transport that you previously added to binding.
Add site bindingGo to the IIS => then Default Website=> right Click on that => Edit Bindings=> click on ADD Button=> add HTTPS bindings there
Details ARE in shown screenshot

Ajax call to WCF Web Service returns 400 Bad Request [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WCF Web Service returns “Bad Request” error when invoked through Javascript
I have a simple WCF web service Service1 with just one method Test() which returns a string. I have deployed this web service on a test machine, but when I try to invoke the Test method from the browser I simply get a 400 Bad Request error. The same happens when I try to invoke the method through an AJAX GET request. But surprisingly, the method returns the correct result when invoked through the WCFTestClient.
Here is the code:
[ServiceContract]
public interface IService1
{
// This method can be called to get a list of page sets per report.
[OperationContract]
[WebGet]
string Test();
}
public class Service1 : IService1
{
public string Test()
{
return "test";
}
}
This is my AJAX request:
var serverUrl1 = 'http://' + baseUrl + ':86/Service1.svc';
function GetTestString()
{
var methodUrl = serverUrl1 + "/Test";
$.ajax({
async: false,
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: methodUrl,
beforeSend: function (XMLHttpRequest) {
//ensures the results will be returned as JSON.
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data) {
ShowQRGSlides(data.d);
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
alert("ERROR: GetAvailablePages() Check your browsers javascript console for more details." + " \n XmlHttpRequest: " + XmlHttpRequest + " \n textStatus: " + textStatus + " \n errorThrown: " + errorThrown);
}
});
}
Here is the web.config file for my web service:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is just the simple web.config which gets automatically generated. I am unable to figure out why this simple web service method is not accessible through the browser or ajax. The same method returns the result when accessed through the WCFTestClient.
Any inputs will be greatly appreciated! Thanks.
You need to add service section to your web.config file. Host does not know that you want to use webHttpBinding unless you tell him.
<services>
<service name="Service1">
<endpoint address=""
binding="webHttpBinding"
contract="IService1" />
</service>
</services>
Link below provides detailed instructions for hosting service in IIS (with wsHttpBinding). You just need to use webHttpBinding instead of wsHttpBinding -
http://msdn.microsoft.com/en-us/library/ms733766.aspx

how to handle "OPTIONS Method" in ASP.NET MVC

My Sencha Touch app is posting a form to my asp.net-mvc-3 WebService, but instead of sending POST it's sending OPTIONS.
I'm reading a similar thread here, but I just don't know how to handle the OPTIONS method in my code.
I did try adding the [AllowAjax] attribute to my Action, however it doesn't seem to exist in MVC3.
OPTIONS /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.5.206/
Access-Control-Request-Method: POST
Origin: http://192.168.5.206
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.71 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Content-Type
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
In my ActionMethod, I'm using the following code.
public JsonpResult CommunicateCard(CommunicateCard communicateCard)
{
// Instantiate a new instance of MailMessage
MailMessage mMailMessage = new MailMessage();
// removed for security/brevity
// Set the body of the mail message
mMailMessage.Body = communicateCard.name; // THIS IS CURRENTLY BLANK :-(
// removed for security/brevity
mSmtpClient.Send(mMailMessage);
// do server side validation on form input
// if it's valid return true
// else return false
// currently returning NULL cuz I don't care at this point.
return this.Jsonp(null);
}
Turns out I had to create an ActionFilterAttribute
namespace WebService.Attributes
{
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", "*");
string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
{
filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin, Content-Type");
}
base.OnActionExecuting(filterContext);
}
}
}
I solved this in a different way in MVC, and IIS. The reason I found this problem was because I wanted to POST data from client side javascript (which JSONP does not work for), and on top of that wanted to allow JSON data which sits inside the Content of the POST request.
In reality your code wants to ignore the first CORS OPTIONS request, as this is likely to be a "site wide setting", and not on a per API call setting.
First I configured IIS to send the CORS response, this can be done through IIS manager (or through web.config updates), if you use IIS then go to the site you want to add these two values:
Access-Control-Allow-Origin to "*" (for testing, for greater security you might want to restrict it to certain calling domains)
Access-Control-Allow-Headers, "Content-Type, Accept" (this is for posting JSON data)
Then I created a custom ActionFilter, which has to be applied for each controller that you want to accept POST data, which could trigger a CORS request. The custom action filter was:
public class CORSActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
{
// do nothing let IIS deal with reply!
filterContext.Result = new EmptyResult();
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
Then at the start of each controller you need to apply this for add in an attribute, e.g.:
[CORSActionFilter]
public class DataSourcesController : Controller
Now I am sure there is a way to do this across your whole MVC solution (solutions welcome), but need to make a BBQ and the solution above works!
I added the following to my <system.webServer> config section:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, X-Requested-With"/>
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
<add name="Access-Control-Allow-Origin" value="*"/>
</customHeaders>
</httpProtocol>
Just to answer the question why "OPTIONS" and not "POST", that is because the browser is implementing CORS (Cross-origin resource sharing ).
This is a two part process of sending the OPTIONS request first, then if the server replies with acceptable conditions the browser then POSTS the actual request with data / content in.
I tried all the answers here and none worked. I eventually realized that browsers will treat the pre-flight check as failed if it returns non 200. In my case, IIS was returning 404, even with the headers. This is because I had 2 attributes on my controller method - [HttpPost] and [HttpOptions]. Apparently, this is not a valid mechanism for expressing multiple verbs. I had to use this attribute instead: [AcceptVerbs(HttpVerbs.Options | HttpVerbs.Post)]
After struggling a lot, I found out the only way to handle CORS preflight request is to handle it with a pair of HttpModule and HttpHandler.
Sending the required headers is not enough. You have to handle the OPTIONS request early and not allow it to reach your controllers, because it will fail there.
The only way that I could do this was with an HttpModule.
I followed this blog post:
http://geekswithblogs.net/abhijeetp/archive/2016/06/04/adding-cors-support-for-asp.net--webapi-the-no-hassle.aspx
To summarize the work, this is the code:
namespace WebAPI.Infrastructure
{
using System;
using System.Web;
using System.Collections;
using System.Net;
public class CrossOriginModule : IHttpModule
{
public String ModuleName
{
get { return "CrossOriginModule"; }
}
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
CrossOriginHandler.AddCorsResponseHeaders(context);
}
public void Dispose()
{
}
}
public class CrossOriginHandler : IHttpHandler
{
#region Data Members
const string OPTIONS = "OPTIONS";
const string PUT = "PUT";
const string POST = "POST";
const string PATCH = "PATCH";
static string[] AllowedVerbs = new[] { OPTIONS, PUT, POST, PATCH };
const string Origin = "Origin";
const string AccessControlRequestMethod = "Access-Control-Request-Method";
const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
const string AccessControlMaxAge = "Access-Control-Max-Age";
const string MaxAge = "86400";
#endregion
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
switch (context.Request.HttpMethod.ToUpper())
{
//Cross-Origin preflight request
case OPTIONS:
AddCorsResponseHeaders(context);
break;
default:
break;
}
}
#endregion
#region Static Methods
public static void AddCorsResponseHeaders(HttpContext context)
{
if (Array.Exists(AllowedVerbs, av => string.Compare(context.Request.HttpMethod, av, true) == 0))
{
var request = context.Request;
var response = context.Response;
var originArray = request.Headers.GetValues(Origin);
var accessControlRequestMethodArray = request.Headers.GetValues(AccessControlRequestMethod);
var accessControlRequestHeadersArray = request.Headers.GetValues(AccessControlRequestHeaders);
if (originArray != null &&
originArray.Length > 0)
response.AddHeader(AccessControlAllowOrigin, originArray[0]);
response.AddHeader(AccessControlAllowCredentials, bool.TrueString.ToLower());
if (accessControlRequestMethodArray != null &&
accessControlRequestMethodArray.Length > 0)
{
string accessControlRequestMethod = accessControlRequestMethodArray[0];
if (!string.IsNullOrEmpty(accessControlRequestMethod))
{
response.AddHeader(AccessControlAllowMethods, accessControlRequestMethod);
}
}
if (accessControlRequestHeadersArray != null &&
accessControlRequestHeadersArray.Length > 0)
{
string requestedHeaders = string.Join(", ", accessControlRequestHeadersArray);
if (!string.IsNullOrEmpty(requestedHeaders))
{
response.AddHeader(AccessControlAllowHeaders, requestedHeaders);
}
}
}
if (context.Request.HttpMethod == OPTIONS)
{
context.Response.AddHeader(AccessControlMaxAge, MaxAge);
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.End();
}
}
#endregion
}
}
and add them to web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<add name="CrossOriginModule" preCondition="managedHandler" type="WebAPI.Infrastructure.CrossOriginModule, Your_Assembly_Name" />
</modules>
<handlers>
<remove name="WebDAV"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="CrossOrigin" verb="OPTIONS" path="*" type="WebAPI.Infrastructure.CrossOriginHandler, Your_Assembly_Name" />
</handlers>
<security>
<authorization>
<remove users="*" roles="" verbs=""/>
<add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,PATCH,DELETE,DEBUG"/>
</authorization>
<requestFiltering>
<requestLimits maxAllowedContentLength="6000"/>
<verbs>
<remove verb="OPTIONS"/>
<remove verb="PUT"/>
<remove verb="PATCH"/>
<remove verb="POST"/>
<remove verb="DELETE"/>
</verbs>
</requestFiltering>
</security>
</system.webServer>
This works for Web API and MVC.

Resources