21

I am trying to add some [WebMethod] annotated endpoint functions to a Webforms style web app (.aspx and .asmx).

I'd like to annotate those endpoints with [EnableCors] and thereby get all the good ajax-preflight functionality.

VS2013 accepts the annotation, but still the endpoints don't play nice with CORS. (They work fine when used same-origin but not cross-origin).

I can't even get them to function cross-origin with the down and dirty

HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");

approach -- my browsers reject the responses, and the cross-origin response headers don't appear.

How can I get CORS functionality in these [WebMethod] endpoints?

3

8 Answers 8

26
+250

I recommend double-checking you have performed all steps on this page: CORS on ASP.NET

In addition to:

Response.AppendHeader("Access-Control-Allow-Origin", "*");

Also try:

Response.AppendHeader("Access-Control-Allow-Methods","*");

Try adding directly in web config:

<system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Methods" value="*" />
       <add name="Access-Control-Allow-Headers" value="Content-Type" />
     </customHeaders>
   </httpProtocol>
</system.webServer>

Failing that, you need to ensure you have control over both domains.

Sign up to request clarification or add additional context in comments.

2 Comments

You are the greatest programmer of the known world! Poems will be written,statuses will be built in your holy name!
this is not the correct answer, the user asked a way to enable CORS on webmethods not webapi
3

FYI, enable CORS in classic webform. In Global.asax

void Application_Start(object sender, EventArgs e)
    {        
        GlobalConfiguration.Configuration.EnableCors();        
        RouteTable.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}/{action}/{id}",
     defaults: new { id = System.Web.Http.RouteParameter.Optional }
 );

Comments

1

If you need the preflight request, e.g. so you can send authenticated requests, you are not able to set Access-Control-Allow-Origin: *. It must be a specific Origin domain.
Also you must set the Access-Control-Allow-Methods and Access-Control-Allow-Headers response headers, if you are using anything besides the defaults.
(Note these constraints are just how CORS itself works - this is how it is defined.)

So, it's not enough to just throw on the [EnableCors] attribute, you have to set values to the parameters:

[EnableCors(origins: "https://www.olliejones.com", headers: "X-Custom-Header", methods: "PUT", SupportsCredentials = true)]

Or if you want to do things manually and explicitly:

HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "https://www.olliejones.com");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Headers", "X-Custom-Header");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "PUT");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Credentials", "true");

One last thing - you do have to call .EnableCors() on initiation. In e.g. MVC or WebAPI, you would call this on HttpConfiguration, when registering the config and such - however I have no idea how it works with WebForms.

Comments

0

If you use the AppendHeader method to send cache-specific headers and at the same time use the cache object model (Cache) to set cache policy, HTTP response headers that pertain to caching might be deleted when the cache object model is used. This behavior enables ASP.NET to maintain the most restrictive settings. For example, consider a page that includes user controls. If those controls have conflicting cache policies, the most restrictive cache policy will be used. If one user control sets the header "Cache-Control: Public" and another user control sets the more restrictive header "Cache-Control: Private" via calls to SetCacheability, then the "Cache-Control: Private" header will be sent with the response.

You can create a httpProtocol in web config for customHeaders.

<httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Methods" values="*" />        
     </customHeaders>
   <httpProtocol>

Comments

0

For the web form, you can use

Response.AddHeader("Access-Control-Allow-Origin", "*");

instead of

Response.AppendHeader("Access-Control-Allow-Origin", "*");

The first one works for old version of ASP.Net Web Form.

Comments

0

In my case,I need to allow mutilple domain. So I add this code:

public class HttpModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += Application_BeginRequest;
    }

    private void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;

        if (context.Request.HttpMethod == "OPTIONS")
        {
            string origin = HttpContext.Current.Request.Headers["Origin"];
            string allowedOrigins = ConfigurationManager.AppSettings["allowOrigin"];

            if (!string.IsNullOrEmpty(origin) && allowedOrigins != null && allowedOrigins.Contains(origin))
            {
                context.Response.AddHeader("Access-Control-Allow-Origin", origin);
                context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
                context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                context.Response.End();
            }
        }

        if (context.Request.HttpMethod == "GET")//I only need get 
        {
            string origin = HttpContext.Current.Request.Headers["Origin"];
            string allowedOrigins = ConfigurationManager.AppSettings["allowOrigin"];

            if (!string.IsNullOrEmpty(origin) && allowedOrigins != null && allowedOrigins.Contains(origin))
            {
                context.Response.AddHeader("Access-Control-Allow-Origin", origin);
                context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
                context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
            }
        }
    }

and the allowOrigin config is in Web.config

  <appSettings>
    <!--fix CORS error-->
      <add key="allowOrigin" value="https://xxxx,https://yyyy,http://localhost:4430"/>
  </appSettings>

Comments

-1

I think your code looks good, but IIS does not send the header entity alone with response expectedly. Please check whether IIS is configured properly.

If CORS doesn't work for your particularity problem, maybe jsonp is another possible way.

2 Comments

Maybe json is another possible way. how?
I guess you mis-read JSONP as JSON. A JSONP response is a standard JSON string wrapped in a function call. Every modern browser is able to evaluate JSONP response without origin domain policy restriction. You can find some solution for c# like this stackoverflow.com/questions/14221429/…
-2

You can do like this in MVC

[EnableCors(origins: "*", headers: "*", methods: "*")]
public ActionResult test()
{
     Response.AppendHeader("Access-Control-Allow-Origin", "*");
     return View();
}

1 Comment

OP is not doing this in MVC as he specified in his post title.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.