C# WebApi添加另一个Get方法

C# WebApi添加另一个Get方法,c#,get,asp.net-web-api,C#,Get,Asp.net Web Api,我有一个相当标准的WebApi,可以执行一些基本的CRUD操作 我试图添加一些不同类型的查找,但不太确定应该如何进行 这是我的FoldersController public class FoldersController : ApiBaseController { //using ninject to pass the unit of work in public FoldersController(IApiUnitOfWork uow) { Uow =

我有一个相当标准的WebApi,可以执行一些基本的CRUD操作

我试图添加一些不同类型的查找,但不太确定应该如何进行

这是我的FoldersController

public class FoldersController : ApiBaseController
{
    //using ninject to pass the unit of work in
    public FoldersController(IApiUnitOfWork uow)
    {
        Uow = uow;
    }

    // GET api/folders
    [HttpGet]
    public IEnumerable<Folder> Get()
    {
        return Uow.Folders.GetAll();
    }

    // GET api/folders/5
    public Folder Get(int id)
    {
        return Uow.Folders.GetById(id);
    }

    // POST api/folders
    public HttpResponseMessage Post(Folder folder)
    {
        Uow.Folders.Add(folder);
        Uow.Commit();

        var response = Request.CreateResponse(HttpStatusCode.Created, folder);

        // Compose location header that tells how to get this Folder
        response.Headers.Location = new Uri(Url.Link(WebApiConfig.DefaultRoute, new { id = folder.Id }));

        return response;
    }

    // PUT api/folders
    public HttpResponseMessage Put(Folder folder)
    {
        Uow.Folders.Update(folder);
        Uow.Commit();
        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }

    // DELETE api/folders/5
    public HttpResponseMessage Delete(int id)
    {
        Uow.Folders.Delete(id);
        Uow.Commit();

        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }
}
只需在我的方法中添加ActionName注释之类的内容
[ActionName(“GetChildren”)]

但那没有飞起来


我走对了吗?如何在不添加其他控制器的情况下执行类似操作?

一种方法是为
GetChildFolders
操作编写一个新路由

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

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

操作是在WebApi控制器中使用两个Get方法的好方法。
以下是我为执行不同操作所做的操作,以及一些操作的可选额外ID参数:

WebApiConfig.cs
中,我有以下几点:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}/{action}/{actionId}",
            defaults: new
            {
                id = RouteParameter.Optional,
                actionId = RouteParameter.Optional,
                action = "DefaultAction"
            }
       );
在控制器中:

    [ActionName("DefaultAction")]
    public AdGetResponse Get(int id)
    {
        ...
    }

    [ActionName("AnotherAction")]
    public HttpResponseMessage GetAnotherAction(int id, int actionId)
    {
    }

按以下方式选择您的路线:

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

config.Routes.MapHttpRoute(
    name: "DefaultApiPlusActionAndFolderid",
    routeTemplate: "api/{controller}/{action}/{folderID}",
    defaults: null,
    constraints: new { action = @"[a-zA-Z]+", folderID = @"\d+" }
);
然后可以使用以下方法:

[ActionName("GetChildren")]
public IEnumerable<Folder> GetChildFolders(int folderID)
{
     return Uow.Folders.GetChildren(folderID);
}
[ActionName(“GetChildren”)]
公共IEnumerable GetChildFolders(int-folderID)
{
返回Uow.Folders.GetChildren(folderID);
}
您可以使用
/api/folders/getchildren/123
调用它。
只要确保方法中的参数值是folderID而不是id。

您可能不喜欢这个答案,但我觉得它是正确的答案。WebAPI被设计为每个实体类型只有5个调用,GET(一个项/列表项)、POST、PUT和DELETE。这允许REST URL,例如Folders/Get/5、Folders/Get等

现在,在您的场景中,您需要ChildFolders,我可以理解这不是不同的对象,但它们在REST(ChildFolders/Get)等方面是不同的实体。我觉得这应该是另一个WebAPI控制器


有很多方法可以修补Http路由以实现这一点,但我觉得这不是Web API的设计初衷,它强制您按照实体类型协议跟踪REST数据。。。否则,为什么不在AJAX调用中使用.NET MVC控制器呢?

正如Chris所说,WebAPI背后的思想是遵循REST模式。考虑到这一点,您可以决定域如何映射到该模式。如果子文件夹是文件夹,并且使用相同的内部逻辑,那么将其放入FoldersController可能非常有意义。如果没有,或者如果您想在子文件夹上执行所有REST方法,那么创建一个ChildFoldersController可能更有意义

既然你的应用程序组织合理,你就可以考虑路由了。WebAPI现在支持属性路由。如果将此行添加到WebApiConfig.Register--
config.maphttpAttribute路由()--像这样:

config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
);
然后,您可以将路线放在动作本身上:

[HttpGet]
[Route("folders/{folderID}/children")] // <-- notice the route here
public IEnumerable<Folder> GetChildFolders(int folderID)
{
     return Uow.Folders.GetChildren(folderID);
}
如果您有其他具有子级的资源,您还可以将控制器作为变量保留在该自定义路由中,并且您仍然可以将该操作放在一个单独的控制器中,该控制器还可以处理对路由“childFolders/{folderID}”的调用

路由非常灵活。只需确保它的设计使api调用方和维护软件的人员(包括您)一目了然


这里有一些属性路由信息:

请注意,
[ActionName(“DefaultAction”)]
注释不是必需的。这仍然不起作用,因为我有两个具有相同参数的Get方法。当我将GetChildFolders发送到该操作时,它会工作,但是当我尝试点击api/folders/5时,它会被混淆为使用什么GetMethod。不确定你在这里做什么,只需谷歌一下,检查一下这个,然后回答:和下面的文章:。这应该能回答你所有的问题。回答得很好,克里斯。然而,我想公开一个API,它为不同的数据集提供服务。假设对于仪表板,我的DashboardController应该有不同的get方法,它将为仪表板中的不同小部件提供数据。我的客户端代码将使用AJAX调用这些不同的get方法。在这里使用WebAPI有意义吗?我认为使用WebAPI很有意义,是的!但是,您已经签出MVC6了吗?控制器和WebAPI是相同的,因此两者之间没有任何区别。我将使用MVC控制器来创建REST API,而不是使用WebAPI项目。
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
);
[HttpGet]
[Route("folders/{folderID}/children")] // <-- notice the route here
public IEnumerable<Folder> GetChildFolders(int folderID)
{
     return Uow.Folders.GetChildren(folderID);
}
// default route
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

// folder children route
config.Routes.MapHttpRoute(
    name: "FolderChildrenApi",
    routeTemplate: "api/folders/{folderID}/children",
    defaults: new { controller = "Folders", action = "GetChildFolders" }
);