Asp.net-Web-Api

在 LINQPad 中使用 WebAPI?

  • April 25, 2015

當我嘗試在 LINQPad 中使用 Selfhosted 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 的單獨控制台項目中工作正常。

當我沒有讓“正常”WebAPI 路由工作時,我開始通過 NuGET 使用 AttributeRouting。

我在瀏覽器中遇到的錯誤是: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'

預設情況下,Web API 會忽略不公開的控制器,並且 LinqPad 類是嵌套的 public,我們在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();
   };
}

引用自:https://stackoverflow.com/questions/14042213