OData除Id之外的字段获取对象

时间:2013-12-30 23:54:29

标签: asp.net-mvc entity-framework asp.net-web-api odata

我刚刚开始使用Web Api OData,我发现自己想要做一些能够做标准ApiController的事情,即从Id字段以外的字段中获取对象。我知道这样做是标准的,例如在基于它的Id:

获取对象时
[Queryable]
    public SingleResult<Group> GetGroup([FromODataUri] int key)
    {
        return SingleResult.Create(db.Groups.Where(group => group.GroupId == key));
    }

但是,如果我想通过groupName字段获取分组,我该怎么办?我尝试过这个类似于ApiController的东西:

控制器:

public Group GetGroup([FromODataUri] string groupName)
    {
        var group = _repository.GetGroupByGroupName(groupName);
        if (group == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }
        return group;
    }

存储库:

public Group GetGroupByGroupName(string groupName)
        {
            Group group = (from u in _db.Groups
                        where u.GroupName == groupName
                        select u).FirstOrDefault();

            return group;
        }

我的WebApiConfig看起来像这样:

public static void Register(HttpConfiguration config)
        {
            config.EnableCors();

            var json = config.Formatters.JsonFormatter;
            json.SerializerSettings.PreserveReferencesHandling =
                Newtonsoft.Json.PreserveReferencesHandling.Objects;

            config.Formatters.Remove(config.Formatters.XmlFormatter);

            // OData
            var modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<City>("Cities");
            modelBuilder.EntitySet<Stage>("Stages");
            modelBuilder.EntitySet<Team>("Teams");
            modelBuilder.EntitySet<Fixture>("Fixtures");
            modelBuilder.EntitySet<Roster>("Rosters");
            modelBuilder.EntitySet<Standing>("Standings");
            modelBuilder.EntitySet<Group>("Groups");

            var model = modelBuilder.GetEdmModel();
            config.Routes.MapODataRoute("ODataRoute", "odata", model);

        }

我希望能够使用odata / Groups / GroupName基于组名获取组对象,但我目前所拥有的组对象不起作用。我该怎么做,或者我是从完全错误的方向接近这个?

2 个答案:

答案 0 :(得分:1)

您已经在使用QueryableAttribute,因此如果您定义了以下内容:

[Queryable]
public IQueryable<Group> Get()
{
    // Returns all groups as a queryable (do not execute query here!)
}

然后,您可以使用ajax请求和任​​何odata查询来访问它,例如:

http://server/Api/Group?$filter=GroupName eq 'test'

查询是在客户端上构建的,不受服务器参数的限制。

答案 1 :(得分:0)

假设您仍然需要调用自定义函数。 OData V4 允许这样做。问题有点陈旧,但我相信它今天仍然有效。

首先,您需要为ODataConventionModelBuilder指定一个命名空间,因为OData V4需要此操作和函数:

var builder = new ODataConventionModelBuilder();
builder.Namespace = "Default";

请注意,这可能会导致IIS给出404,因为IIS会解释该点。为了防止这种情况,add the following到您的Web.config:

<system.webServer>
    <handlers>
      <clear/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" 
          verb="*" type="System.Web.Handlers.TransferRequestHandler" 
          preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

然后,您还需要声明该函数:

builder.EntitySet<Group>("Groups").EntityType
    .Collection
    .Function("GetGroupByName")
    .ReturnsFromEntitySet<Group>("Groups")
    .Parameter<string>("name");

注意函数是在COLLECTION上声明的,所以它绑定到它。然后是ODataController方法:

[ODataRoute("Groups/Default.GetGroupByName(name={name})")]
[HttpGet]
public IHttpActionResult GetGroupByName([FromODataUri]string name)
{
    return Ok(new Group() or whatever);
}

只有在使用参数时,才需要ODataRoute注释。它按顺序定义:实体集,命名空间,方法和参数。

然后您可以使用:

http://localhost:xxxx/api/Groups/Default.GetByGroupName(name='sausage')

另外,请参阅this SO answer以传递多个参数