【问题标题】:Understanding routes, how do I create two 'identical' routes that can be both GET and POST?了解路由,如何创建两个可以是 GET 和 POST 的“相同”路由?
【发布时间】:2013-01-02 11:51:17
【问题描述】:

以前,我有两种方法,一种用[WebGet] 标记,另一种用[WebInvoke(Method = "POST"] 标记

当我对我指定的 URL 执行 GET 或 POST 时,它总是会调用正确的方法。

网址是:

POST: fish-length
GET: fish-length?start-date={startDate}&pondId={pondId}

现在我正在使用 web api,我必须单独定义我的路由,如下所示:

    RouteTable.Routes.MapHttpRoute(
        name: "AddFishLength",
        routeTemplate: "fish-length",
        defaults: new
        {
            controller = "FishApi",
            action = "AddFishLength"
        });


    RouteTable.Routes.MapHttpRoute(
       name: "GetFishLength",
       routeTemplate: "fish-length?start-date={startDate}&pondId={pondId}",
       defaults: new
       {
           controller = "FishApi",
           action = "GetFishLength"
       });

但是第二条路线不起作用,因为您不允许在 routeTemplate 中使用 ?。

我可以将 URL 格式更改为 fish-length/{startDate}/{pondId} 之类的格式,但这确实不是公开服务的好方法。

有没有更好的方法来做到这一点?另外因为我之前对同一个 url 进行了 POST 和 GET,所以我需要确保我的路由方法仍然允许这样做。假设上述方法有效,我仍然不确定它如何正确路由。

【问题讨论】:

    标签: asp.net-mvc-4 asp.net-web-api asp.net-mvc-routing


    【解决方案1】:

    不,您不需要定义单独的路线。您只需要一条路线:

    RouteTable.Routes.MapHttpRoute(
        name: "AddFishLength",
        routeTemplate: "fish-length",
        defaults: new
        {
            controller = "FishApi",
        }
    );
    

    然后遵循 ApiController 操作的 RESTful 命名约定:

    public class FishApiController: ApiController
    {
        // will be called for GET /fish-length
        public HttpResponseMessage Get()
        {
            // of course this action could take a view model
            // and of course that this view model properties
            // will automatically be bound from the query string parameters
        }
    
        // will be called for POST /fish-length
        public HttpResponseMessage Post()
        {
            // of course this action could take a view model
            // and of course that this view model properties
            // will automatically be bound from the POST body payload
        }
    }
    

    所以假设你有一个视图模型:

    public class FishViewModel
    {
        public int PondId { get; set; }
        public DateTime StartDate { get; set; }
    }
    

    继续修改您的控制器操作以采用此参数:

    public class FishApiController: ApiController
    {
        // will be called for GET /fish-length
        public HttpResponseMessage Get(FishViewModel model)
        {
        }
    
        // will be called for POST /fish-length
        public HttpResponseMessage Post(FishViewModel model)
        {
        }
    }
    

    您显然可以为不同的操作使用不同的视图模型。

    【讨论】:

    • 我无法弄清楚它是如何映射到动作的。假设我的方法被称为GetFishLength,那么它怎么知道调用它,而不是GetFishName?您没有在路由信息中指定操作的名称。
    【解决方案2】:

    您不能在路由模板中指定查询字符串参数 - 但只要您有一个与参数名称匹配的方法,WebApi 就应该足够聪明,可以自行解决。

    public HttpResponseMessage Get(string id) 对应于{controller}?id=xxx 的请求

    但是,如果没有看到实际对象,就很难判断您应该如何解决您的案件。例如。 WebApi 不喜欢 Get 请求中的复杂类型,并且它仅以特定方式支持发布数据中的 url 编码内容。

    至于 Get 和 Post 的区别非常简单 - WebApi 知道您在发送请求时使用了哪种方法,然后它会查找以 Get/Post 开头或以 HttpGet/Post 属性装饰的方法名称。

    我建议查看以下文章 - 它们帮助我了解了它的工作原理:

    http://www.west-wind.com/weblog/posts/2012/Aug/16/Mapping-UrlEncoded-POST-Values-in-ASPNET-Web-API

    http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-17
      • 2018-10-20
      • 2021-11-07
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 2018-04-20
      相关资源
      最近更新 更多