2012-12-26 31 views
15

當我試圖在LINQPad中使用Selfhosted WebAPI時,我只是不斷收到類似控制器不存在的錯誤。在LINQPad中使用WebAPI?

是否必須爲WebAPI(控制器/類)創建單獨的程序集,然後在查詢中引用它們?

下面是我使用

#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(); 
    } 
} 

此代碼工作在一個單獨的控制檯項目在VS2012晴好時的代碼。

我開始使用通過NuGET的AttributeRouting,當我沒有得到「正常的」WebAPI路由工作。

我在瀏覽器中得到的錯誤是:No HTTP resource was found that matches the request URI 'http://192.168.0.196:8181/players/allPlayers'.

更多的錯誤:在默認情況下No type was found that matches the controller named 'PlayerObject'

+1

我公司生產的LINQ腳本與您的代碼(在缺少的部分填充一些虛擬類/方法),並加入'config.Routes.Cast ().LogTo(Console.Out);'。我確實看到路線'URL:players/allPlayers GET,HEAD,OPTIONS'。這似乎表明路線設置正確。我確實沒有找到與瀏覽器中名爲'PlayerObject'的控制器相匹配的類型,但這與您的錯誤看起來不同(可能與我的虛擬類太虛擬相關)。 –

+0

我甩掉了路線,我可以看到他們已經註冊,但是當試圖進入頁面時,我仍然遇到了錯誤。我發佈了一個產生錯誤的新代碼。 – NoLifeKing

+0

@FrankvanPuffelen我確實得到了和你一樣的錯誤,但只有在LINQPad中,當我將它移入VS2012時,它開始無障礙地工作。我總是可以開始使用VS,但LINQPad中.Dump()的簡單性對我來說很有價值。因爲我也使用我的筆記本電腦作爲此webapi的「客戶端」。 :) – NoLifeKing

回答

16

的Web API將忽略控制器,不公開,以及LinqPad類嵌套公共,我們也有類似的問題scriptcs

您必須添加一個自定義控制器解析器,該解析器將繞過該限制,並允許您從手動執行的程序集中發現控制器類型。

這實際上已經被修復了(現在的Web API控制器只需要可見不公開),但發生在9月份,自主主機的最新穩定版本是從8月份開始。

因此,補充一點:

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(); 
    } 

} 

,然後註冊對你的配置,就大功告成了:

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

這是一個完整的工作示例,我只是測試對LinqPad。請注意,您必須以管理員身份運行LinqPad,否則您將無法在端口上收聽。

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

有一個強制LINQPad不能嵌套類型的技巧:用#define NONEST –

+0

開始你的查詢啊,真好!感謝喬 –

+0

雖然我有點困惑,這段代碼去了哪裏?我看過你的博客文章,並試圖弄清楚這段代碼是作爲'C#程序'進入LinqPad還是進入我的Web API應用程序?還是兩者兼而有之? – atconway