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>