かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ASP.NET Odata v4.0でアクション定義

ファンクションの次はアクション。こいつも、ファンクションと同じで、全体、エンテティ、エンテティのコレクションの3つに定義できます。Add, Add2, Add3という名前で定義を以下のようにやります。

using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions; // MapODataServiceRouteに必要
using WebApplication5.Controllers;

namespace WebApplication5
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            var b = new ODataConventionModelBuilder();
            b.EntitySet<Person>("People");
            
            var addAction = b.Action("Add");
            addAction.Returns<double>();
            addAction.Parameter<double>("x");
            addAction.Parameter<double>("y");

            var addTypeAction = b.EntityType<Person>().Action("Add2");
            addTypeAction.Returns<double>();
            addTypeAction.Parameter<double>("x");
            addTypeAction.Parameter<double>("y");

            var addCollectionAction = b.EntityType<Person>().Collection
                .Action("Add3");
            addCollectionAction.Returns<double>();
            addCollectionAction.Parameter<double>("x");
            addCollectionAction.Parameter<double>("y");

            config.MapODataServiceRoute(
                "ODataRoute",
                "odata",
                b.GetEdmModel());
        }
    }
}

そして、コントローラにメソッドを定義します。ActionはHttpPostで定義します。

[HttpPost]
[ODataRoute("Add")]
public IHttpActionResult Add(ODataActionParameters p)
{
    return Ok((double)p["x"] + (double)p["y"]);
}

[HttpPost]
public IHttpActionResult Add2(int key, ODataActionParameters p)
{
    return Ok((double)p["x"] + (double)p["y"]);
}

[HttpPost]
public IHttpActionResult Add3(ODataActionParameters p)
{
    return Ok((double)p["x"] + (double)p["y"]);
}

引数がODataActionParametersとまぁいけてない感じですね…。

T4テンプレートが生成してくれるクライアントからは以下のような感じで呼び出せます。

var c = new Container(new Uri("http://localhost:7650/odata"));
// Add
var answer = c.Add(10, 3).GetValue();
Console.WriteLine(answer);

// Add2
var answer2 = c.People.ByKey(new Dictionary<string, object>
    {
        { "Id", 33 }
    })
    .Add2(10, 3)
    .GetValue();
Console.WriteLine(answer2);

// Add3
var answer3 = c.People.Add3(10, 3).GetValue();
Console.WriteLine(answer3);

Actionは、Postで送られる関係か、引数や戻り値に複雑な型を渡しても平気な点がいいかもですね。