天天看点

快速搭建Web Api OData V4服务端

VS2015可以自动化搭建Web Api OData V3服务端,但是不能自动化搭建OData V4服务端。微软官网给出了一个例程,https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint,可以手动编码搭建OData V4服务端。

经过试验,发现可以把OData V3服务端升级到OData V4,可以省很多事。以下为操作步骤。

1.自动化搭建OData V3服务端

新建Asp.NET空白项目,打勾Web API。

快速搭建Web Api OData V4服务端

NuGet下载EF 6.1.3。

定义实体类,定义数据库。

public class Book
    {
        public int id { get; set; }

        public string Name { get; set; }//书名

        public DateTime PublishDate { get; set; }//出版日期

        public string Author { get; set; }//作者

        public float Price { get; set; }//价格
    }

    public class MyBookDB : DbContext
    {
        public DbSet<Book> Books { get; set; }

        public MyBookDB() : base("dbConn")
        {
            Database.SetInitializer<MyBookDB>(new DropCreateDatabaseIfModelChanges<MyBookDB>());
        }

    }
           

编译项目,添加OData V3控制器

快速搭建Web Api OData V4服务端
快速搭建Web Api OData V4服务端

然后运行项目,浏览http://localhost:54611/odata,验证OData V3服务端可以访问。

快速搭建Web Api OData V4服务端

2.升级到OData V4服务端

NuGet下载Microsoft.AspNet.Odata。注意,6.0是不行的,5.10.0可以,其他版本我没有一一测试。

快速搭建Web Api OData V4服务端

然后,打开BooksController控制器,把命名空间替换一下

//using System.Web.Http.OData;//OData V3
using System.Web.OData;//OData V4
           

再打开WebApiConfig,把命名空间替换一下

//using System.Web.Http.OData.Builder;//OData V3
//using System.Web.Http.OData.Extensions;//OData V3
using System.Web.OData.Builder;//OData V4
using System.Web.OData.Extensions;//OData V4
           

配置OData路由的函数小改一下

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Book>("Books");
//config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());//OData V3
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());//OData V4
           

然后再次编译项目,浏览http://localhost:54611/odata,可以看到显示内容已经变了,已经升级到OData V4

快速搭建Web Api OData V4服务端

3.创建OData客户端

参考https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-client-app

新建一个Winform项目,在扩展和更新工具里搜索OData Client Code Generator,下载安装,网络非常慢……

快速搭建Web Api OData V4服务端

重启VS2015,给项目添加OData Client文件,取名为BookODataClient.tt

快速搭建Web Api OData V4服务端

忽略安全警告,系统自动创建了BookODataClient.tt,打开这个文件,给public const string MetadataDocumentUri赋值OData V4服务端路径。

快速搭建Web Api OData V4服务端

把OData V4服务端运行起来,对BookODataClient.tt运行自定义工具

快速搭建Web Api OData V4服务端

然后,系统自动创建了一大堆代码……

4.测试OData功能

然后就可以对数据库增删改查了。

private string serviceUri;
        private Default.Container container;

        private void Form1_Load(object sender, EventArgs e)
        {
            serviceUri = "http://localhost:54611/odata";
            container = new Default.Container(new Uri(serviceUri));
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            List<Book> books = new List<Book>()
            {
                new Book() { Name = "射雕英雄传", PublishDate = new DateTime(, , ), Author = "金庸", Price = f },
                new Book() { Name = "神雕侠侣", PublishDate = new DateTime(, , ), Author = "金庸", Price = f },
                new Book() { Name = "倚天屠龙记", PublishDate = new DateTime(, , ), Author = "金庸", Price = f },
                new Book() { Name = "小李飞刀", PublishDate = new DateTime(, , ), Author = "古龙", Price = f },
                new Book() { Name = "绝代双骄", PublishDate = new DateTime(, , ), Author = "古龙", Price = f },
            };

            foreach (Book book in books)
            {
                container.AddToBooks(book);
            }

            var serviceResponse = container.SaveChanges();

            foreach (var operationResponse in serviceResponse)
            {
                //返回多个结果201
               Debug.Print("Response: {0}", operationResponse.StatusCode);
            }
        }

        private void btnModify_Click(object sender, EventArgs e)
        {
            var book = container.Books.Where(x => x.Name == "绝代双骄").FirstOrDefault();
            if (book != null)
            {
                book.Price += ;
                container.UpdateObject(book);

                var serviceResponse = container.SaveChanges();

                foreach (var operationResponse in serviceResponse)
                {
                    //没有返回结果
                    Debug.Print("Response: {0}", operationResponse.StatusCode);
                }
            }
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            var book = container.Books.Where(x => x.Name == "绝代双骄").FirstOrDefault();
            if (book != null)
            {
                container.DeleteObject(book);

                var serviceResponse = container.SaveChanges();

                foreach (var operationResponse in serviceResponse)
                {
                    //返回结果204
                    Debug.Print("Response: {0}", operationResponse.StatusCode);
                }
            }
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            //ToList()才获取查询结果
            this.dataGridView1.DataSource = container.Books.Where(x => x.Author == "金庸").OrderByDescending(x => x.PublishDate).ToList();
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            //ToList()才获取查询结果
            //服务端分页
            this.dataGridView1.DataSource = container.Books.OrderByDescending(x => x.Price).Skip().Take().ToList();
        }
           
快速搭建Web Api OData V4服务端

为什么要费这么大劲把OData V3升级到V4?当然不是蛋疼,而是因为V4支持获取数据库记录:int count = container.Books.Count();

可以把OData V4服务端部署到IIS,用Fiddler抓包,查看每次发送和收到的原始数据。

注意:部署OData V4服务端到IIS的时候,要修改Web.config,支持DELETE谓词

<system.webServer>
    <modules>
      <!--允许DELETE谓词-->
      <remove name="WebDAVModule" />
    </modules><handlers>
      <!--允许DELETE谓词-->
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>