2012-12-26 11 views
15

Quando ho provato a utilizzare il WebAPI Selfhosted in LINQPad, ho continuato a ricevere lo stesso errore che un controller per la classe non esisteva.Utilizzo di WebAPI in LINQPad?

Devo creare assembly separati per WebAPI (Controllers/Classes) e quindi farli riferimento nella mia query?

Ecco il codice che sto utilizzando

#region namespaces 
using AttributeRouting; 
using AttributeRouting.Web.Http; 
using AttributeRouting.Web.Http.SelfHost; 
using System.Web.Http.SelfHost; 
using System.Web.Http.Routing; 
using System.Web.Http; 
#endregion 

public void Main() 
{ 

    var config = new HttpSelfHostConfiguration("http://192.168.0.196:8181/"); 
    config.Routes.MapHttpAttributeRoutes(cfg => 
    { 
     cfg.AddRoutesFromAssembly(Assembly.GetExecutingAssembly()); 
    }); 
    config.Routes.Cast<HttpRoute>().Dump(); 

    AllObjects.Add(new UserQuery.PlayerObject { Type = 1, BaseAddress = "Hej" }); 

    config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; 
    using(HttpSelfHostServer server = new HttpSelfHostServer(config)) 
    { 
     server.OpenAsync().Wait(); 
     Console.WriteLine("Server open, press enter to quit"); 
     Console.ReadLine(); 
     server.CloseAsync(); 
    } 

} 

public static List<PlayerObject> AllObjects = new List<PlayerObject>(); 

public class PlayerObject 
{ 
    public uint Type { get; set; } 
    public string BaseAddress { get; set; } 
} 

[RoutePrefix("players")] 
public class PlayerObjectController : System.Web.Http.ApiController 
{ 
    [GET("allPlayers")] 
    public IEnumerable<PlayerObject> GetAllPlayerObjects() 
    { 
     var players = (from p in AllObjects 
        where p.Type == 1 
        select p); 
     return players.ToList(); 
    } 
} 

Questo codice funziona bene quando in un progetto console separata in VS2012.

Ho iniziato a utilizzare AttributeRouting tramite NuGET quando non ho ottenuto il "normale" WebAPI-routing per funzionare.

L'errore ho ottenuto nel browser era: No HTTP resource was found that matches the request URI 'http://192.168.0.196:8181/players/allPlayers'.

Errore aggiuntivo: No type was found that matches the controller named 'PlayerObject'

+1

ho prodotto una sceneggiatura LINQ con il codice (compilando le parti mancanti con alcune classi/metodi fittizio) e ha aggiunto 'config.Routes.Cast () .LogTo (Console.Out);'. Vedo il percorso 'URL: player/allPlayers GET, HEAD, OPTIONS'. Quindi sembra che il percorso sia impostato correttamente. Ricevo "Non è stato trovato alcun tipo che corrisponda al controller denominato" PlayerObject "nel browser, ma sembra diverso dal tuo errore (e probabilmente correlato al fatto che le mie classi fittizie sono troppo fittizie). –

+0

Ho scaricato i percorsi e ho potuto vedere che sono registrati, ma quando ho provato ad andare alla pagina ho ancora ottenuto l'errore. Ho pubblicato un nuovo codice che produce l'errore. – NoLifeKing

+0

@FrankvanPuffelen Ricevo lo stesso errore, ma solo in LINQPad, quando ho spostato questo in VS2012, ha iniziato a funzionare senza problemi. Potrei sempre iniziare a usare VS, ma la facilità di .Dump() in LINQPad vale molto per me. Poiché uso anche il mio laptop come "client" per questo webapi. :) – NoLifeKing

risposta

16

Web API per default ignorerà i controllori che non sono pubblici, e le classi LINQPad sono nidificato pubblico, abbiamo avuto simili problema in scriptcs

È necessario aggiungere un resolver controller personalizzato, che ignorerà tale limite e consentirà di rilevare manualmente i tipi di controller dal gruppo di esecuzione.

Questo è stato effettivamente risolto già (ora controllori API Web devono solo essere Visibile non pubblico), ma quello che è successo nel mese di settembre e l'ultima versione stabile di serie di auto è da agosto.

Quindi, aggiungere questo:

public class ControllerResolver: DefaultHttpControllerTypeResolver { 

    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) { 
     var types = Assembly.GetExecutingAssembly().GetExportedTypes(); 
     return types.Where(x => typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(x)).ToList(); 
    } 

} 

E quindi registrare contro la configurazione, e il gioco è fatto:

var conf = new HttpSelfHostConfiguration(new Uri(address)); 
conf.Services.Replace(typeof(IHttpControllerTypeResolver), new ControllerResolver()); 

Ecco un esempio di lavoro pieno, ho appena testato contro LINQPad. Si noti che è necessario eseguire LinqPad come amministratore, altrimenti non sarà possibile ascoltare in una porta.

public class TestController: System.Web.Http.ApiController { 
    public string Get() { 
     return "Hello world!"; 
    } 
} 

public class ControllerResolver: DefaultHttpControllerTypeResolver { 
    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) { 
     var types = Assembly.GetExecutingAssembly().GetExportedTypes(); 
     return types.Where(x => typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(x)).ToList(); 
    } 
} 

async Task Main() { 
    var address = "http://localhost:8080"; 
    var conf = new HttpSelfHostConfiguration(new Uri(address)); 
    conf.Services.Replace(typeof(IHttpControllerTypeResolver), new ControllerResolver()); 

    conf.Routes.MapHttpRoute(
     name: "DefaultApi", 
     routeTemplate: "api/{controller}/{id}", 
     defaults: new { id = RouteParameter.Optional } 
    ); 

    var server = new HttpSelfHostServer(conf); 
    await server.OpenAsync(); 

    // keep the query in the 'Running' state 
    Util.KeepRunning(); 
    Util.Cleanup += async delegate { 
     // shut down the server when the query's execution is canceled 
     // (for example, the Cancel button is clicked) 
     await server.CloseAsync(); 
    }; 
} 
+10

C'è un trucco per forzare LINQPad a non annidare i tipi: inizia la tua query con #define NONEST –

+0

ah, bello! grazie Joe –

+0

Sono un po 'confuso però, dove va questo codice? Ho visto il tuo post sul blog e sto cercando di capire se questo codice va in LinqPad come un 'Programma C#' o va nella mia applicazione API Web? O è in entrambi? – atconway