【问题标题】:Actions in MVC 4 WebAPIMVC 4 WebAPI 中的操作
【发布时间】:2013-12-29 22:43:06
【问题描述】:

我一直关注http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api,在创建以下控制器后,我得到了意想不到的结果...

public class ProductsController : ApiController
{
    Product[] products = new Product[] 
    { 
        new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, 
        new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, 
        new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } 
    };

    public IEnumerable<Product> GetAllProducts()
    {
        return products;
    }

    public Product GetProductById(int id)
    {
        var product = products.FirstOrDefault((p) => p.Id == id);
        if (product == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        return product;
    }
}

我希望能够像这样拨打电话:

/api/products/GetAllProducts

但这不起作用。相反,我可以简单地调用:

/api/产品

实际上执行GetAllProducts() 中描述的过程。为什么这没有按预期工作?

【问题讨论】:

    标签: c# asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    因为在 WebApi 框架中,假设您需要“Get”方法。

    你熟悉不同的http动词吗?发布、获取、放置、删除?当您在浏览器中输入 url 时,它会发出 Get 请求。框架看到了这一点,并假设您想要 GetAllProducts。

    如果您有一个 DeleteAllProducts,并向/api/products 发出删除请求,它将运行该请求。

    如果您有一个GetProduct(int id) 并向api/products/1 发出一个Get 请求(例如,通过在浏览器地址栏中输入),它将执行GetProcuct(1)

    认为更像是一个基于 CRUD 的控制器。您可以只使用名为 Get、Post、Put、Delete 的操作,它会根据使用的 http 动词运行这些操作。想要更新产品?它类似于public ActionResult Post(int id, [FromBody]Product p),您可以通过对/api/products/1 的POST 请求调用它。当然,需要在请求正文中发送 Product Json/XML 才能使序列化工作。

    【讨论】:

    【解决方案2】:

    使用Url:/api/products/GetAllProducts 不起作用,因为您的 Web Api 仅支持默认路由:

    configuration.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    

    为了让它像你期望的那样工作,你需要在顶部添加一个支持action的路由:

    configuration.Routes.MapHttpRoute(
              name: "CustomizedApi",
              routeTemplate: "api/{controller}/{action}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
    

    至于第二个URL:/api/products,它之所以有效是因为:

    默认路由中的id 是可选的(RouteParameter.Optional)。

    来自link

    框架只选择与请求的HTTP方法(GET、POST、PUT、DELETE)匹配的动作,确定如下:

    • 具有属性的 HTTP 方法:AcceptVerbs、HttpDelete、HttpGet、HttpHead、HttpOptions、HttpPatch、HttpPost 或 HttpPut。

    • 否则,如果控制器方法的名称以“Get”、“Post”、“Put”、“Delete”、“Head”、“Options”或“Patch”开头,那么按照约定action 支持该 HTTP 方法。

    • 如果以上都不是,该方法支持POST。

    在您的情况下,如果您从浏览器发出请求,它应该是一个 GET 请求,因此该请求将映射到以 Get 开头的操作(方法 GetAllProducts

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2012-09-11
      相关资源
      最近更新 更多