了解路由,如何创建两个可以同时为GET和POST的“相同”路由?

时间:2013-01-02 11:51:17

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

以前,我有两种方法,我用[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"
       });

但是第二条路线不起作用,因为在路线模板中不允许?

我可以将网址格式更改为类似fish-length/{startDate}/{pondId}的内容,但这实际上不是公开服务的好方法。

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

2 个答案:

答案 0 :(得分:0)

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

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)
    {
    }
}

显然,您可以为不同的操作设置不同的视图模型。

答案 1 :(得分:0)

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

public HttpResponseMessage Get(string id)将对应{controller}?id=xxx

的请求

但是,如果没有看到实际的对象,你应该如何解决你的问题。例如。 WebApi不喜欢Get请求中的复杂类型,并且它仅以特定方式支持post数据中的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