Web API (独立)和 Web API ASP.NET MVC 之间的区别



我创建了一个包含Web APIASP.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。您可能想在此处和此处进一步了解此主题

最新更新