かずきのBlog@hatena

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

ASP.NET WebAPIのOData v4で登録更新削除

Put, Patch, Post, Deleteメソッドを作ればよしなにやってくれるみたいです。

using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.OData;

namespace WebApplication5.Controllers
{
    public class PeopleController : ODataController
    {
        public IQueryable<Person> Get()
        {
            return Enumerable.Range(1, 10)
                .Select(i => new Person
                {
                    Id = i, 
                    Name = "tanaka" + i
                })
                .AsQueryable();
        }

        public IHttpActionResult Get(int key)
        {
            return Ok(new Person { Id = key, Name = "tanaka" + key });
        }

        public IHttpActionResult Patch([FromODataUri] int key, Delta<Person> delta)
        {
            var p = new Person();
            delta.Patch(p);
            Debug.WriteLine(p.Name);
            return Updated(p);
        }

        public IHttpActionResult Put([FromODataUri] int key, Person p)
        {
            Debug.WriteLine("Put");
            return Updated(p);
        }

        public IHttpActionResult Post(Person p)
        {
            Debug.WriteLine("Post");
            p.Id = 999;
            return Created(p);
        }

        public IHttpActionResult Delete([FromODataUri] int key)
        {
            Debug.WriteLine("Delete");
            return StatusCode(HttpStatusCode.NoContent);
        }
    }

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

確認

ODataのリクエストを手で送るのはメンドクサイのでここでクライアントコードの実行を試してみます。OData v4のクライアントコードはT4テンプレートで作るみたいです。

拡張機能と更新プログラムでOData v4 Client Code Generatorをインストールします。そうすると、新規作成に、OData Clientというのが追加されます。追加されるttファイルの中にMetadataDocumentUriという箇所があるのでodataのURLを追加します。今回の例だとhttp://localhost:7650/odata/$metadataを指定するとよさげです。

<#@ include file="ODataClient1.ttinclude" #>
<#+
public static class Configuration
{
    // The URI of the metadata document. The value must be set to a valid service document URI or a local file path 
    // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx"
    // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of
    // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail.
    public const string MetadataDocumentUri = "http://localhost:7650/odata/$metadata"; // ここ!

    // The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false.
    public const bool UseDataServiceCollection = true;

Containerというクラスが作られるので、それを使って検索、更新、登録、削除をしてみました。

using ConsoleApplication1.Default;
using ConsoleApplication1.WebApplication5.Controllers;
using Microsoft.OData.Client;
using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var c = new Container(new Uri("http://localhost:7650/odata"));
            {
                // Get()
                foreach (var p in c.People.Execute())
                {
                    Console.WriteLine("{0} {1}", p.Id, p.Name);
                }
            }
            Console.WriteLine("----");
            {
                // Get(key)
                var r = c.People
                    .Where(x => x.Id == 100);
                foreach (var p in r)
                {
                    Console.WriteLine("{0} {1}", p.Id, p.Name);
                }
            }
            Console.WriteLine("---");
            {
                // Patch
                var p = c.People.Where(x => x.Id == 100).ToArray().First();
                p.Name = "kimura";
                // 変更があったとマーク
                c.ChangeState(p, EntityStates.Modified);
                c.SaveChanges();
            }
            Console.WriteLine("---");
            {
                // Post
                var p = new Person { Name = "homura" };
                c.AddToPeople(p);
                c.SaveChanges();
                Console.WriteLine(p.Id); // 999
            }
            Console.WriteLine("---");
            {
                // Delete
                var p = c.People.Execute();
                c.DeleteObject(p.First());
                c.SaveChanges();
            }
        }
    }
}

ふむ、とりあえず順調。