4

我正在尝试为我认为非常简单的事情设置 Web API 路由。但是,Web API 中的路由似乎与不同的 HTTP 动词不一致。假设我有这个控制器有这些动作......

public class AvalancheController : ApiControllerBase
{

    // GET api/avalanche
    public IEnumerable<Avalanche> Get() {}

    // GET api/avalanche/5
    public Avalanche Get(int id) {}

    // GET api/avalanche/ActionTest/5
    [ActionName("ActionTest")]
    public Avalanche GetActionTest(int id) {}

    // GET api/avalanche/ActionTest/2
    [ActionName("ActionTest2")]
    public Avalanche GetActionTest2(int id) {}

    // POST api/avalanche
    public void Post([FromBody]Avalanche value) {}

    // PUT api/avalanche/5
    public void Put(int id, [FromBody]Avalanche value) {}

    // PUT api/avalanche/test/5
    [ActionName("Test")]
    public void PutTest(int id, [FromBody]Avalanche value) {}

    // DELETE api/avalanche/5
    public void Delete(int id) {}
}

我定义了以下路线...

    config.Routes.MapHttpRoute(
        name: "ActionRoutes",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new
            {
                controller = "Avalanche",
                action = "(ActionTest|ActionTest2|Test)"
            }
    );


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

然后我最终定义了以下路线......

GET api/Avalanche/ActionTest/{id}
GET api/Avalanche/ActionTest2/{id}
PUT api/Avalanche/Test/{id}
GET api/Avalanche   
POST api/Avalanche  
DELETE api/Avalanche/{id}

为什么不选择默认 PUT 路由?默认 GET 和默认 PUT 的路由有什么不同?我已经尝试以各种可以想象的方式装饰这些功能,但我得到了相同的结果。

主要是我想知道如何获取默认的 PUT 路由。如果您对如何修改这些路由有任何建议,这样我就不必为每个控制器指定一个路由来指定动作名称,这也很棒。

谢谢!

伊恩

编辑:我今天早上注意到以下路线也没有被定义..

GET api/Avalanche/{id}
4

1 回答 1

1

很高兴您找到了解决问题的方法。但我会根据我对 REST 服务的学习提供我的反馈。REST webservice 的想法是将每个 url 解析为一个资源(或者可能是实体),并根据 HttpVerb 来决定操作。在这种情况下,您有三个 GET 操作,可以很好地配合您的修改。

但我认为控制器也可以重新安排为具有单一的 GET 操作并具有单一的责任,从而更好的可维护性。例如:

雪崩控制器

public class AvalancheController : ApiControllerBase
{
    public IEnumerable<Avalanche> GET()
    {

    }

    public void POST(Avalanche avalanche)
    {

    }
}

可以假设在顶层处理所有雪崩,下面是要定义的操作。

GET:返回所有雪崩
POST:插入新的雪崩
PUT:未使用
DELETE:未使用

雪崩详细信息控制器

public class AvalancheDetailsController : ApiControllerBase
{
    public Avalanche GET(int id)
    {

    } 


    public int PUT(int id)
    {

    }

    public int DELETE(int id)
    {

    }
}

可以假设处理单个雪崩,下面是要定义的操作。

GET:返回单个雪崩
POST:未使用
PUT:更新单个雪崩
DELETE:删除单个雪崩

现在我假设我们对控制器有明确的区分。在您提到的 OP 中,可以有不同的 GET 操作,但它只返回单个Avalanche. 因此,我会更改 GET 方法以将对象作为输入并检查值,即

public class AvalanceRequest
{
  public int? Id {get;set;}
  public string Name {get;set;}
}


   public class AvalancheDetailsController : ApiControllerBase
    {
        public Avalanche GET(AvalanceRequest request)
        {
           //write business logic based on parameters
           if(request.Id.HasValue)
           //return avalanche;
           if(request.Name.IsNullOrEmpty())
           //return avalanche
        } 
        //other methods
  }

处理 URL,我并没有真正使用 WebAPI,而是尝试使用 ServiceStack 来开发 REST 服务。它允许附加 url 独立于控制器名称。

Url
api/Avalanche --> AvalancheController (操作基于HttpVerb调用)
api/Avalanche/Id --> AvalancheDetailsController (操作基于HttpVerb调用)

我不知道是否可以在 WebAPI 中同样附加 url,否则您最终将拥有默认配置并通过调用。api/Avalanche 和 api/AvalancheDetails/id。

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

我很抱歉发了这么长的帖子,希望它有意义。

于 2013-03-14T16:06:40.157 回答