6

EntitySetController を使用して oData Web API コントローラーを作成していますが、合計レコード数を取得する以外はすべて正常に機能します。

コントローラーは次のように定義されます。

public class MyODataController : EntitySetController<Entity1, int> where TEntity : class
{
    public override IQueryable<Entity1> Get()
    {
        return EntityDatabase.Get();
    }
}

私がカウントを呼び出すとき:

http://localhost:44789/oData/MyOData/$count

エラーが表示されます: 無効なアクションが検出されました。「$count」は、「Collection([Entity1 Nullable=False])」にバインドできるアクションではありません。

4

5 に答える 5

14

残念ながら、Web API はすぐに使用できる $count をまだサポートしていませんが、将来のバージョンではサポートする必要があります。当面は、次のクラスを定義してサポートを追加できます。

public class CountODataRoutingConvention : EntitySetRoutingConvention
{
    public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
    {
        if (controllerContext.Request.Method == HttpMethod.Get && odataPath.PathTemplate == "~/entityset/$count")
        {
            if (actionMap.Contains("GetCount"))
            {
                return "GetCount";
            }
        }
        return null;
    }
}

public class CountODataPathHandler : DefaultODataPathHandler
{
    protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment)
    {
        if (segment == "$count")
        {
            return new CountPathSegment();
        }
        return base.ParseAtEntityCollection(model, previous, previousEdmType, segment);
    }
}

public class CountPathSegment : ODataPathSegment
{
    public override string SegmentKind
    {
        get
        {
            return "$count";
        }
    }

    public override IEdmType GetEdmType(IEdmType previousEdmType)
    {
        return EdmCoreModel.Instance.FindDeclaredType("Edm.Int32");
    }

    public override IEdmEntitySet GetEntitySet(IEdmEntitySet previousEntitySet)
    {
        return previousEntitySet;
    }

    public override string ToString()
    {
        return "$count";
    }
}

それらを MapODataRoute に登録します。

IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0, new CountODataRoutingConvention());
config.Routes.MapODataRoute("OData", "odata", GetModel(), new CountODataPathHandler(), routingConventions);

そしてコントローラーに、このメソッドを追加します:

public HttpResponseMessage GetCount(ODataQueryOptions<TEntity> queryOptions)
{
    IQueryable<TEntity> queryResults = queryOptions.ApplyTo(Get()) as IQueryable<TEntity>;
    int count = queryResults.Count();
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StringContent(count.ToString(), Encoding.UTF8, "text/plain");
    return response;
}

GetCount() をすべてのコントローラーにコピーする必要がないようにするには、GetCount を定義する EntitySetController から派生する基本クラスを定義できます。

于 2013-05-20T14:23:19.900 に答える
7

以下を使用する場合:

http://localhost:44789/oData/MyOData?$inlinecount=allpages

次に、合計カウントが get リターンに含まれます。

于 2013-05-20T15:02:04.127 に答える
2

localhost:..../?$inlinecount=allpages&$skip=0&$top=0 これはバッターだと思います。コードを追加する必要はありません。

于 2015-01-26T10:44:14.373 に答える
2

OData v4.0 用の最新パッケージ Web API 2.2 には、$count サポートがあります。

于 2014-07-25T20:32:25.947 に答える
0

1 つのオプションは、$top=0 を $inlinecount=allpages と組み合わせて使用​​することです。ちょっとした回避策ですが、うまく機能することがわかりました。単一の整数値よりもオブジェクトを返したいと思います。これはフィルターでもうまく機能します:

http://localhost:44789/oData/MyOData?$filter=MyFilter&$top=1&$inlinecount=allpages
于 2016-07-28T13:26:17.403 に答える