使用服务数据库上下文作为 WebApi OData 上下文
Using A Service DB Context as WebApi OData Context
我正在尝试使用 Webapi 2 创建 OData 服务。
我已经创建了一个适用于本地上下文的工作示例。现在,我想使用由单独的 WCF 服务提供的上下文。
WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.AddODataQueryFilter();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
控制器Class:
public class ProductsController : ODataController
{
static Uri ServiceRoot = new Uri("http://localhost:4684/BDBWcfService.svc/");
public ProductsController()
{
//db.Configuration.ProxyCreationEnabled = false;
InitDB();
}
public void InitDB()
{
db = new BDBODataService.NORTHWNDEntities(ServiceRoot);
}
DataServiceContext Context = new DataServiceContext(ServiceRoot, DataServiceProtocolVersion.V3);
BDBODataService.NORTHWNDEntities db = null;
//NORTHWNDEntities db = new NORTHWNDEntities();
// GET api/values
//[EnableQuery]
//public IQueryable<Product> Get()
//{
// return db.Products;
//}
[EnableQuery]
public IQueryable<BDBODataService.Product> Get()
{
return db.Products;
//return Context.CreateQuery<BDBODataService.Product>("Products");
}
// GET api/values/5
//Naming the attribute as key allows the model binder to sync when
// calling urls like http://localhost:7428/odata/Products(1) key here = 1
//[EnableQuery(MaxExpansionDepth=3)]
//public SingleResult<Product> Get([FromODataUri]int key)
//{
// var res = db.Products.Where(p => p.ProductID == key);
// return SingleResult.Create(res);
//}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
很抱歉这些评论是我尝试过的其他解决方案。
当我执行代码时,我要么收到 406 不可接受的错误,要么得到一个空体而不是我的 Json。
有人知道我能做些什么来解决这个问题吗?
显然只需使用即可启用 OData 支持:
config.AddODataQueryFilter();
在本地工作,但如果来自服务,您需要明确声明您的模型。我不是 100% 确定这是我所有问题的原因,我最终调试了 System.Web.Http.OData 和 .net 4.5 框架,发现根本原因是 DefaultContentNegotiator.cs 一直说它不能Iqueryable 类型,因为请求无法解析 EDM 模型。在像这样明确声明我的模型后,一切都开始工作了:
public static IEdmModel GetServiceModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<BDBODataService.Order>("Orders");
/* this explicitly Ignores a specific property.
* notice if you call http://localhost:7428/odata/Products(1)?$expand=Category
* picture will be hidden */
var cat = builder.EntitySet<BDBODataService.Category>("Categories");
cat.EntityType.Ignore(c => c.Picture);
builder.EntitySet<BDBODataService.CustomerDemographic>("CustomerDemographics");
builder.EntitySet<BDBODataService.Customer>("Customers");
builder.EntitySet<BDBODataService.Employee>("Employees");
builder.EntitySet<BDBODataService.Order_Detail>("OrderDetails");
builder.EntitySet<BDBODataService.Region>("Regions");
builder.EntitySet<BDBODataService.Shipper>("Shippers");
builder.EntitySet<BDBODataService.Supplier>("Suppliers");
builder.EntitySet<BDBODataService.Territory>("Territories");
builder.EntitySet<BDBODataService.Orpan>("Orphans");
var products = builder.EntitySet<BDBODataService.Product>("Products");
return builder.GetEdmModel();
}
我正在尝试使用 Webapi 2 创建 OData 服务。 我已经创建了一个适用于本地上下文的工作示例。现在,我想使用由单独的 WCF 服务提供的上下文。
WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.AddODataQueryFilter();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
控制器Class:
public class ProductsController : ODataController
{
static Uri ServiceRoot = new Uri("http://localhost:4684/BDBWcfService.svc/");
public ProductsController()
{
//db.Configuration.ProxyCreationEnabled = false;
InitDB();
}
public void InitDB()
{
db = new BDBODataService.NORTHWNDEntities(ServiceRoot);
}
DataServiceContext Context = new DataServiceContext(ServiceRoot, DataServiceProtocolVersion.V3);
BDBODataService.NORTHWNDEntities db = null;
//NORTHWNDEntities db = new NORTHWNDEntities();
// GET api/values
//[EnableQuery]
//public IQueryable<Product> Get()
//{
// return db.Products;
//}
[EnableQuery]
public IQueryable<BDBODataService.Product> Get()
{
return db.Products;
//return Context.CreateQuery<BDBODataService.Product>("Products");
}
// GET api/values/5
//Naming the attribute as key allows the model binder to sync when
// calling urls like http://localhost:7428/odata/Products(1) key here = 1
//[EnableQuery(MaxExpansionDepth=3)]
//public SingleResult<Product> Get([FromODataUri]int key)
//{
// var res = db.Products.Where(p => p.ProductID == key);
// return SingleResult.Create(res);
//}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
很抱歉这些评论是我尝试过的其他解决方案。
当我执行代码时,我要么收到 406 不可接受的错误,要么得到一个空体而不是我的 Json。
有人知道我能做些什么来解决这个问题吗?
显然只需使用即可启用 OData 支持:
config.AddODataQueryFilter();
在本地工作,但如果来自服务,您需要明确声明您的模型。我不是 100% 确定这是我所有问题的原因,我最终调试了 System.Web.Http.OData 和 .net 4.5 框架,发现根本原因是 DefaultContentNegotiator.cs 一直说它不能Iqueryable 类型,因为请求无法解析 EDM 模型。在像这样明确声明我的模型后,一切都开始工作了:
public static IEdmModel GetServiceModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<BDBODataService.Order>("Orders");
/* this explicitly Ignores a specific property.
* notice if you call http://localhost:7428/odata/Products(1)?$expand=Category
* picture will be hidden */
var cat = builder.EntitySet<BDBODataService.Category>("Categories");
cat.EntityType.Ignore(c => c.Picture);
builder.EntitySet<BDBODataService.CustomerDemographic>("CustomerDemographics");
builder.EntitySet<BDBODataService.Customer>("Customers");
builder.EntitySet<BDBODataService.Employee>("Employees");
builder.EntitySet<BDBODataService.Order_Detail>("OrderDetails");
builder.EntitySet<BDBODataService.Region>("Regions");
builder.EntitySet<BDBODataService.Shipper>("Shippers");
builder.EntitySet<BDBODataService.Supplier>("Suppliers");
builder.EntitySet<BDBODataService.Territory>("Territories");
builder.EntitySet<BDBODataService.Orpan>("Orphans");
var products = builder.EntitySet<BDBODataService.Product>("Products");
return builder.GetEdmModel();
}