【发布时间】:2014-04-11 13:08:54
【问题描述】:
这是我的 TransferController 类的草图。
所有这些都是 Web API 代码。
public class TransferController : ApiController
{
[HttpGet, ActionName("Queue")]
public IEnumerable<object> GetQueue(Guid sessionId) {...}
[HttpDelete, ActionName("Delete")]
public void Delete(Guid sessionId, Guid fileId) {...}
[HttpGet, ActionName("Cancel")]
public bool Cancel(Guid sessionId, Guid fileId) {...}
[HttpGet, ActionName("UploadedBytes")]
public long GetUploadedByteCount(Guid sessionId, Guid fileId) {...}
[HttpGet, ActionName("DownloadUrl")]
public string GetDownloadUrl(string fileId) {...}
[HttpPost, ActionName("FileChunk")]
public void PostFileChunk([FromUri]Guid sessionId, [FromUri]Guid fileId) {...}
[HttpPost, ActionName("UploadDefinition")]
public Guid PostUploadItem([FromBody]UploadDefinition uploadDef) {...}
}
这是路由。
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}"
);
config.Routes.MapHttpRoute(
name: "DefaultApiDefaultMethod",
routeTemplate: "api/{controller}"
);
}
这是调用。
$.ajax({
url: "api/Transfer/Queue",
data: { sessiondId: login.SessionId() }
})
.done(function (result) {
history.push(new UploadItem());
for (var i = 0; i < result.length; i++) {
var ui = new UploadItem(result[i]);
history.push(ui);
}
})
.fail(function (result) {
app.showMessage(JSON.parse(result.responseText).Message);
});
这就是结果。
No HTTP resource was found that matches the request URI 'http://localhost:54770/api/Transfer/Queue?sessiondId=0e2c47b9-e674-446d-a06c-ce16932f9580'.
这是我的 UserController 类的草图。
public class UserController : ApiController
[HttpGet, ActionName("Authenticate")]
public object Authenticate(string email, string password) {...}
[HttpPost]
public void Register([FromBody]UserDefinition userDef) {...}
[HttpGet, ActionName("Pulse")]
public bool Pulse(Guid sessionId) {...}
}
由于我无法理解的原因,我在 UserController 中调用任何东西都没有问题。参数以完全相同的方式编组,并且 same 路由正在使用中。
下面的 Darrel Miller 使用单元测试来验证路由。坦率地说,我因为没有想到这一点而自责,现在我也这样做了。
但他展示的测试实际上只测试 URL 的解析。比如这个测试通过了
public void TestMvc4RouteWibble()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var route =
config.Routes.GetRouteData(new HttpRequestMessage()
{
RequestUri = new Uri("http://localhost:54770/api/Transfer/Wibble?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580&fileId=0e2c47b9-e674-446d-a06c-ce16932f9581") //?
});
Assert.IsNotNull(route);
Assert.AreEqual("Transfer", route.Values["controller"]);
Assert.AreEqual("Wibble", route.Values["action"]);
}
尽管 Transfer 控制器上明显没有 Wibble 方法。
另外,路由对象实际上并不是一个 HttpRoute 对象,它是一个 HttpRouteData 对象。但这是微不足道的纠正。 HttpRoute 对象可用作 HttpRouteData 对象的属性。
public void TestMvc4RouteWibble()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var routeData =
config.Routes.GetRouteData(new HttpRequestMessage()
{
RequestUri = new Uri("http://localhost:54770/api/Transfer/Wibble?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580&fileId=0e2c47b9-e674-446d-a06c-ce16932f9581") //?
});
Assert.IsNotNull(routeData);
Assert.AreEqual("Transfer", routeData.Values["controller"]);
Assert.AreEqual("Wibble", routeData.Values["action"]);
}
它又具有 Handler 属性。然而,这比它可能提供的信息更少,因为 null 处理程序只是意味着(来自 MSDN)
如果为 null,则默认处理程序将消息分派到 IHttpController 的实现。
现在,我的控制器是从 ApiController 派生的,它当然实现了 ExecuteAsync 方法,这是 IHttpController 接口指定的唯一方法。我想这意味着如果我了解更多,我可以测试该方法的执行。
【问题讨论】:
-
我会避免获得
Cancel -
不是所有动作都应该返回 ActionResult 吗?我不知道 Apicontroller,但在 Controller 中,您必须具有 Actionresult 或派生类型的返回类型...
-
这是 Web API。从类继承自 ApiController 的事实来看,这一点应该很明显,但我会在问题中适当地指出它。
-
有人会搜索“ASP.NET WEB API 路由难题”吗?您的标题应该是某人会搜索的内容。与论坛不同,这里的标题应该是对您的问题的描述。
标签: asp.net-web-api asp.net-web-api-routing