2013-06-14 13 views
7

Attualmente sto sperimentando endpoint OData in API Web ASP.NET MVC 4. Mi piace il concetto e cerco di trovare modi efficaci per utilizzarlo nel nostro progetto. Una domanda che ho è la seguente: abbiamo un servizio che è in grado di restituire un IQueryable e prende il nome di un'entità come input:ASP.NET WebAPI: controller generico per endpoint OData

public IQueryable GetAll(string entityName); 

In API Web standard (al contrario di controllori OData) posso crea un controller generico, che può essere chiamato nella forma/api/entities/{entityName} e restituisce IQueryable. In caso di un controller OData, svolgo le seguenti specifiche entità passi:

  1. registro delle entità nel modello.
  2. Creare un controller separato per ciascuna entità che deriva da EntitySetController <>.

Desidero utilizzare il servizio generico ed evitare il più possibile le implementazioni specifiche per entità. Il primo passo può essere facilmente automatizzato se il servizio può restituire un elenco delle entità e dei tipi corrispondenti. Questo lascia il passaggio 2, perché fino ad ora ho bisogno di creare un controller specifico per ogni entità. Voglio anche evitarlo e creare un controller generico che utilizza il servizio generico.

Qualcuno può consigliare una soluzione, forse influenzando il routing OData?

risposta

11

È possibile creare una convenzione di instradamento personalizzata che seleziona lo stesso controller indipendentemente dall'entità impostata. Esempio,

public class CustomControllerRoutingConvention : IODataRoutingConvention 
{ 
    public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap) 
    { 
     return null; 
    } 

    public string SelectController(ODataPath odataPath, HttpRequestMessage request) 
    { 
     return "SomeFixedContrllerNameWithoutTheControllerSuffix"; 
    } 
} 

È possibile registrare tale convenzione il routing utilizzando il seguente codice,

IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault(); 
routingConventions.Insert(0, new CustomControllerRoutingConvention()); 
config.Routes.MapODataRoute("OData", "odata", builder.GetEdmModel(), new DefaultODataPathHandler(), routingConventions); 
+1

È necessario controllare l'odataPath per le entità nulle. Questo indica le query di meta-dati che devono andare alla rotta predefinita. if (odataPath.EdmType == null || odataPath.EntitySet == null) return null; – xt1

+0

Questo ha anche risolto un problema con l'ottenimento di v3 e v4 nello stesso progetto, poiché non è possibile avere nomi di controller duplicati e il tentativo di utilizzare un attributo route su un nome di controller diverso restituisce un 406. Per la convenzione nome controller EntityV4Controller, restituendo odataPath.NavigationSource.Name + "V4" troverà il controller. Il metodo –

+0

@ xt1 per il controllo delle query dei metadati è apparentemente comune, ma non affidabile. Il nostro progetto ha situazioni in cui 'odataPath.EntitySet == null', ma non è una richiesta $ metadata. Ho trovato che il controllo di una combinazione di 'ODataSegmentKinds.ServiceBase' e' ODataSegmentKinds.Metadata' è più affidabile.(Questo è per un servizio V3.) –

6

mi è venuta contro lo stesso problema, e finito per scrivere una consuetudine IHttpControllerSelector invece di un IODataRoutingConvention. IODataRoutingConvention sembra una buona opzione se il tuo controller generico non richiede generici :). Ma dal momento che IODataRoutingConvention.SelectController() restituisce solo una stringa, non vedo come funzionerà per creare un'istanza di un controller con parametri di tipo generico.

Ho deciso che questo problema richiede una buona soluzione open source generica, quindi ne ho creato uno: http://entityrepository.codeplex.com. Ora è in fase di prerelease, ma al momento sto lavorando molto su questo. Penso che ci sia molto di più che scegliere il controller giusto, ci sono schemi generali da definire per i controller condivisi e, per impostazione predefinita, l'API Web OData prevede proprietà di navigazione fortemente tipizzate e fortemente denominate che rendono difficile creare un'implementazione riutilizzabile.

Problemi correlati