2014-11-17 8 views
7

Sto utilizzando lo DynamicPolicyProviderFactory come descritto here. Qui di seguito è la mia versione del DynamicPolicyProviderFactory:L'API Web abilitata per CORS non riesce ad aggiungere l'intestazione

public class DynamicPolicyProviderFactory : ICorsPolicyProviderFactory 
{ 
    private readonly HashSet<Regex> _allowed; 

    public DynamicPolicyProviderFactory(IEnumerable allowedOrigins) 
    { 
     _allowed = new HashSet<Regex>(); 

     foreach (string pattern in allowedOrigins.Cast<string>() 
      .Select(Regex.Escape) 
      .Select(pattern => pattern.Replace("*", "w*"))) 
     { 
      _allowed.Add(new Regex(pattern, RegexOptions.IgnoreCase)); 
     } 

     if (_allowed.Count >= 1) 
      return; 

     //if nothing is specified, we assume everything is. 
     _allowed.Add(new Regex(@"https://\w*", RegexOptions.IgnoreCase)); 
     _allowed.Add(new Regex(@"http://\w*", RegexOptions.IgnoreCase)); 
    } 

    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request) 
    { 
     var route = request.GetRouteData(); 
     var controller = (string)route.Values["controller"]; 
     var corsRequestContext = request.GetCorsRequestContext(); 
     var originRequested = corsRequestContext.Origin; 
     var policy = GetPolicyForControllerAndOrigin(controller, originRequested); 
     return new CustomPolicyProvider(policy); 
    } 

    private CorsPolicy GetPolicyForControllerAndOrigin(string controller, string originRequested) 
    { 
     // Do lookup to determine if the controller is allowed for 
     // the origin and create CorsPolicy if it is (otherwise return null) 

     if (_allowed.All(a => !a.Match(originRequested).Success)) 
      return null; 

     var policy = new CorsPolicy(); 
     policy.Origins.Add(originRequested); 
     policy.Methods.Add("GET"); 
     policy.Methods.Add("POST"); 
     policy.Methods.Add("PUT"); 
     policy.Methods.Add("DELETE"); 
     return policy; 
    } 
} 

public class CustomPolicyProvider : ICorsPolicyProvider 
{ 
    private readonly CorsPolicy _policy; 

    public CustomPolicyProvider(CorsPolicy policy) 
    { 
     this._policy = policy; 
    } 

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     return Task.FromResult(this._policy); 
    } 
} 

invito a far registrare i cors vincere la WebApiConfig.cs

config.EnableCors(); 
config.SetCorsPolicyProviderFactory(new DynamicPolicyProviderFactory(Settings.Default.AllowedDomains)); 

E le mie impostazioni delle applicazioni di essere passati:

<MyApp.Properties.Settings> 
    <setting name="AllowedDomains" serializeAs="Xml"> 
    <value> 
     <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <string>http://localhost</string> 
     <string>http*://*.domain1.com</string> 
     <string>http*://*.domain2.com</string> 
     </ArrayOfString> 
    </value> 
    </setting> 
</MyApp.Properties.Settings> 

Nonostante queste impostazioni, l'intestazione Access-Control-Allow-Origin non è presente sul mio r esponsi se faccio una richiesta da http://mg.domain1.com a http://localhost. Sto usando Web Api 2.2 e Microsoft.AspNet.Cors 5.2.2.

edit: Ho scoperto che se uso l'attributo EnableCors sul controller, o abilitare globalmente (config.EnableCors(new EnableCorsAttribute("*", "*", "*"));) funziona, quindi deve essere qualcosa con la mia fabbrica dinamica. La cosa frustrante è che DynamicPolicyProvider è copia/incollato da un altro progetto che sto usando che funziona bene.

Edit 2:! successo ... Ho attivato tracing e hanno trovato l'errore

The collection of headers 'accept,content-type' is not allowed 

Così ho appena modificato il metodo GetPolicyForControllerAndOrigin per consentire loro. Ora tutto funziona, eccetto che sono confuso perché non ho dovuto saltare attraverso questo telaio nel mio altro progetto (quello da cui ho copiato DynamicPolicyProviderFactory).

+1

È incredibile il modo in cui hanno reso l'installazione CORS con diversi modi diversi di come è possibile impostarlo dove ognuno "funziona quasi" e la documentazione è terribile, in tutto il luogo e non spiega la metà delle cose che si ' si suppone di implementare per farlo funzionare. – pootzko

+0

@pootzko Sono assolutamente d'accordo! Anche Mike_G, posso semplicemente inserire DynamicPolicyProviderFactory.cs nella cartella principale o deve andare in una determinata cartella? Di cosa si tratta: '', non riesco a trovarlo da nessuna parte in Web.config. È l'appSettings? – Si8

+1

@ Si8 'DynamicPolicyProviderFactory' è come qualsiasi altra classe e può essere organizzato in qualsiasi cartella di codice. per 'MyApp.Poperties.Settings', è nel web.config, ma se vuoi un'interfaccia per modificare quella sezione specifica, fai clic con il tasto destro del mouse sul tuo progetto in VS> Proprietà> Impostazioni –

risposta

4

Abilita tracing nell'app. Dovresti vedere un errore

The collection of headers 'accept,content-type' is not allowed 

Basta aggiungere questi alle intestazioni consentite per la politica e tutto dovrebbe funzionare.

Problemi correlati