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。
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控制器
然后运行项目,浏览http://localhost:54611/odata,验证OData V3服务端可以访问。
2.升级到OData V4服务端
NuGet下载Microsoft.AspNet.Odata。注意,6.0是不行的,5.10.0可以,其他版本我没有一一测试。
然后,打开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
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,下载安装,网络非常慢……
重启VS2015,给项目添加OData Client文件,取名为BookODataClient.tt
忽略安全警告,系统自动创建了BookODataClient.tt,打开这个文件,给public const string MetadataDocumentUri赋值OData V4服务端路径。
把OData V4服务端运行起来,对BookODataClient.tt运行自定义工具
然后,系统自动创建了一大堆代码……
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();
}
为什么要费这么大劲把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>