在 web api 控制器中制作通用查询/getbyspecification?

Making a generic query / getbyspecification in web api controller?

我有一个带有一些 CRUD 操作的典型 API。我通常需要根据不同的参数获取某些对象。

一种方法是使用如下方法:

GetProjectsByCustomerId(int customerId);
GetProjectsBySigneeId(int signeeId);

但是,在我的服务层(ProjectService 在这种情况下)我通常使用如下方法,其中 ProjectSpecification 通常有很多字段甚至列表:

public IEnumerable<Project> GetBySpecification(ProjectSpecification projectSpecification)

这意味着,在我的梦想世界中,我希望有这样的端点:

我的问题是 - 这是怎么做到的

我的第一次尝试是在我的 ProjectController 中添加这个(调用我的 ProjectService):

public class ProjectsController : ApiController
{
    public IEnumerable<Project> GetProjects(ProjectSpecification projectSpecification)
    {
        var projects = _projectService.GetBySpecification(projectSpecification);
        return projects;
    }
}

但是假设我打开这个 URL:

/api/Projects?CustomerId=2

这未被解析为 ProjectSpecification 视图模型。但是,如果我将我的控制器签名更改为:

public IEnumerable<Project> GetProjects(int customerid) { }

它会工作,因为它是一个简单的类型。

我当然可以构建一些参数地狱,但我想我缺少一些非常明显的 MVC 魔法 - 可能在路由中? :-)

参考文档

Parameter Binding in ASP.NET Web API : [FromUri]

To force Web API to read a complex type from the URI, add the [FromUri] attribute to the parameter.

例如假设

public class ProjectSpecification {
    public int CustomerId { get; set; }
    //...other properties
}

public class ProjectsController : ApiController {
    [HttpGet]
    public IHttpActinoResult GetProjects([FromUri]ProjectSpecification projectSpecification) {
        return Ok(projectSpecification);
    }
}

客户端可以将 CustomerId 值放入查询字符串中。

例如:

/api/Projects?CustomerId=2

和 Web API 将使用它们来构建 ProjectSpecification 并将 CustomerId 设置为 2