2015-02-06 15 views
6

Desidero creare un oggetto per richiesta http all'interno di ActionFilter e passare questo oggetto al controller. Request.Properties Finora ho provato [] come la seguentePassare un oggetto da ActionFilter.OnActionExecuting() a un ApiController

public class DbReadonlyAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     actionContext.Request.Properties["CustomObjectKey"] = new MyClass(); 

E ho anche cercato di assegnare il nuovo oggetto diretto ad una classe ControllerBase.

public class DbReadonlyAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     var controller = (MyControllerBase) actionContext.ControllerContext.Controller; 
     controller.StorageContextFactory = new MyClass(); 

Il problema è che né tecnica offre un'istanza di MyClass al controller perché la nuova proprietà [ "CustomObjectKey"] si perde nella pipeline WebAPI per il momento in un metodo di controllo viene richiamato.

Il controller viene nuovamente istanziato dalla pipeline di Webapi dopo il filtro di chiamata all'azione OnActionExecuting().

I punti di interruzione confermano che la pipeline di Webapi pianifica il seguente flusso di eventi durante una singola richiesta http.

  • costruttore MyControllerBase()
  • MyAuthenticationFilter
  • Filtro OnActionExecuting()
  • costruttore MyControllerBase()
  • MyController.MethodA()

La doppia istanziazione di MyControler è dispari, ma in questo momento sto cercando qualsiasi tecnica per passare un oggetto appena creato da un filtro di azione a un controller.

Edit-1: MyAuthorizationFilter menzionato nella v1 di questa domanda è in realtà un filtro di autenticazione. Ancora indagando

Soluzione: il bug era in un altro filtro. Dopo aver rimosso il mio filtro di autenticazione, il problema riportato in questa domanda è andato via.

risposta

13

Sarà necessario utilizzare il metodo Request.Properties per la raccolta.

public class DbReadonlyAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     actionContext.Request.Properties.Add(new KeyValuePair<string, object>("CustomObjectKey", new MyClass())); 

È possibile recuperare questo valore dal controller api.

object _customObject= null; 

if (Request.Properties.TryGetValue("CustomObjectKey", out _customObjectKey)) 
{ 
    MyClass myObject = (MyClass)_customObject; 
} 
+0

Grazie per il vostro contributo, ancora sto ottenendo il problema dopo aver applicato la modifica del codice e ora il sospetto che ho un problema più profondo con il concatenamento asincrono nel mio filtro di autenticazione . – camelCase

+1

Ho usato il codice che ho incollato nella mia risposta. Funziona bene per me. –

+0

Ho semplificato il problema rimuovendo il mio filtro di autenticazione globale dichiarato in WebApiConfig come config.Filters.Add (x); L'oggetto che passa dal mio filtro di azioni al controller usando il tuo esempio e le mie proprietà originali ["CustomObjectKey"] = la tecnica funziona per entrambi gli esempi. Ora sto studiando il motivo per cui il mio filtro di autenticazione sta causando problemi, ad es. l'istanziazione del doppio controller. Se correggo questo, tornerò e valuterò la tua risposta dal momento che il tuo suggerimento mi ha indotto a cercare un problema più profondo. – camelCase

0

Un altro modo per passare variabili da ActionFilter.OnActionExecuting() per un ApiController:

public class CustomFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext actionContext) 
    { 
     actionContext.ControllerContext.RequestContext.RouteData.Values["CustomValue"] = "CustomValue"; 
    } 
} 

Prestare attenzione ad utilizzare ActionFilterAttribute per API Web:

System.Web. Http.Filters.ActionFilterAttribute

Non per MVC classica:

System.Web.Mvc.ActionFilterAttribute

Usando:

[CustomFilter] 
public class SomeController : ApiController 
{ 
    string customValue = RequestContext.RouteData.Values.ToDictionary(x => x.Key, y => y.Value)["user_id"].ToString(); 
    //... 
}