我创建了一个包含Web API
的ASP.NET MVC
项目,并且我创建了一个空项目,其中只选择了Web API
,我试图理解为什么它们的行为不同。
据我所知,它们都具有如下定义的路由定义:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
但我想了解为什么控制器中定义的函数的行为不同。
在我的ASP.NET MVC
解决方案中,我可以在一个控制器下创建多个函数:
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
我不必添加任何attributes
,至少对于get,我可以调用单个函数:
http://localhost/api/test/GetProduct/1 http://localhost/api/test/GetProducts
在Web API
唯一的解决方案中,我必须将其定义为:
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
但除非我将[HttpGet]
属性添加到我的 HelloWorld 函数中,否则上述内容将不起作用。
此外,我似乎无法在一个控制器中定义多个功能,因为它是在ASP.NET MVC
解决方案中完成的。定义与上述相同的函数不起作用,或者即使我定义了下面的函数
[HttpGet]
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
[HttpGet]
public IHttpActionResult GetTime()
{
return Ok(DateTime.Now.ToString());
}
我收到以下错误:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Multiple actions were found that match the request: HelloWorld on type
MyProject.Controllers.TestController GetTime on type
MyProject.Controllers.TestController
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at
System.Web.Http.Controllers.ApiControllerActionSelector.
ActionSelectorCacheItem.SelectAction(HttpControllerContext
controllerContext) at System.Web.Http.ApiController.
ExecuteAsync(HttpControllerContext controllerContext, CancellationToken
cancellationToken) at System.Web.Http.Dispatcher.
HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
</StackTrace>
当我定义单个函数时,它有效,但与我的ASP.NET MVC
解决方案中定义的Web API
相反,当我调用以下内容时
http://localhost/api/test/HelloWorld
它似乎并不关心函数名称的调用,因为如果我调用以下任何一项,它将起作用:
http://localhost/api/test http://localhost/api/test/GoodBye
并且仅当我提供无效的控制器名称时才会失败,即
http://localhost/api/mytest
您能否解释一下 2 之间的区别,理想情况下我必须做什么才能使独立的 Web API 的行为方式与在Asp.net MVC
中定义时的行为方式相同
谢谢。
更新-1
下面是 2 个行为明显不同的好例子,但我不明白为什么,因为两者都被称为"带有 ASP.NET MVC 的 Web API"。
使用 ASP.NET MVC Web API 创建简单服务,以供 Windows 应用商店和 Windows Phone 应用程序访问
ASP.NET Web API 2 入门 (C#)
编辑:
起初我很生气,我误解了你的询问,因此给了你错误的答案。
在 Web API 中,不能定义两个提供完全相同路径的函数。但是你可以像使用函数一样重载它们。
public IEnumerable<Product> GetAllProducts() {}
public IHttpActionResult GetProduct(int id) {}
到目前为止,这两个功能有所不同,它们服务于不同的路径:
localhost/api/products/
localhost/api/products/{id}/
另一方面,以下函数都服务于localhost/api/test/
[HttpGet]
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
[HttpGet]
public IHttpActionResult GetTime()
{
return Ok(DateTime.Now.ToString());
}
您的第二个问题是命名,主要是为什么您无法在没有[HttpGet]
的情况下定义HelloWorld()
。这是因为 Web API 会自动将具有关键字(如 Get 或 Delete)作为其名称一部分的函数映射到相应的 Http 函数。
仅当函数名称不符合这些命名约定或应提供多个 Http 方法时,才需要添加 Http-Attribute。这里描述了它
我希望你的问题现在得到解答。
奥里格:
默认路由和后续关于要执行什么函数的决定在 MVC 和 Web API 之间是不同的
默认网页 API:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
默认 MVC:
config.Routes.MapHttpRoute(
name: "DefaultMvc",
routeTemplate: "/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
对于Web Api,路由取决于控制器名称,并且进一步选择了哪种Http方法以及实际具有已使用此方法标记的功能的控制器。因此和进一步的标签
另一方面,Mvc通过控制器名称和操作名称路由到所需的功能。
Web Api 2 增加了更多的可能性,允许您定义 AttributeRoutes。您可能想在此处和此处进一步了解此主题