C# 使用服务数据库上下文作为WebApi OData上下文

C# 使用服务数据库上下文作为WebApi OData上下文,c#,wcf,odata,asp.net-web-api2,C#,Wcf,Odata,Asp.net Web Api2,我正在尝试使用Webapi 2创建OData服务。 我已经创建了一个适用于本地上下文的工作示例。现在,我想使用一个单独的WCF服务提供的上下文 WebApiConfig.cs: public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{

我正在尝试使用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();
    }
控制器类:

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)
    {
    }
}
公共类产品控制器:ODataController
{
静态Uri ServiceRoot=新Uri(“http://localhost:4684/BDBWcfService.svc/");
公共产品控制器()
{
//db.Configuration.ProxyCreationEnabled=false;
InitDB();
}
public void InitDB()
{
db=新的BDBODataService.NORTHWNDEntities(ServiceRoot);
}
DataServiceContext上下文=新的DataServiceContext(ServiceRoot,DataServiceProtocolVersion.V3);
BDBODataService.NORTHWNDEntities db=null;
//NORTHWNDEntities db=新的NORTHWNDEntities();
//获取api/值
//[启用查询]
//公共IQueryable Get()
//{
//返回数据库产品;
//}
[启用查询]
公共IQueryable Get()
{
返回数据库产品;
//返回Context.CreateQuery(“产品”);
}
//获取api/values/5
//将属性命名为键允许模型绑定器在
//像这样调用URLhttp://localhost:7428/odata/Products(1) 这里的键=1
//[启用查询(MaxExpansionDepth=3)]
//公共单结果获取([FromODataUri]int-key)
//{
//var res=db.Products.Where(p=>p.ProductID==key);
//返回SingleResult.Create(res);
//}
//后api/值
公共作废帖子([FromBody]字符串值)
{
}
//将api/values/5放入
公共void Put(int id,[FromBody]字符串值)
{
}
//删除api/values/5
公共无效删除(int-id)
{
}
}
很抱歉,这些评论只是我尝试过的其他解决方案

当我执行代码时,我要么收到406个不可接受的错误,要么得到一个空的正文而不是Json


有人知道我能做些什么来解决这个问题吗?

显然,只需使用以下命令即可启用OData支持:

config.AddODataQueryFilter();
在本地工作,但如果来自服务,则需要显式声明模型。我不是100%确定这是我所有问题的原因,我最终调试了System.Web.Http.OData和.net 4.5框架,发现根本原因是DefaultContentCongregator.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();
    }
公共静态IEdmModel GetServiceModel()
{
ODataConventionModelBuilder=新ODataConventionModelBuilder();
建造商实体集(“订单”);
/*这会显式忽略特定属性。
*如果你打电话通知我http://localhost:7428/odata/Products(1) ?$expand=类别
*图片将被隐藏*/
var cat=builder.EntitySet(“类别”);
cat.EntityType.Ignore(c=>c.Picture);
builder.EntitySet(“CustomerDemographics”);
建筑商实体集(“客户”);
建筑商实体集(“员工”);
builder.EntitySet(“订单详细信息”);
建筑商实体集(“区域”);
建造商实体集(“托运人”);
建造商实体集(“供应商”);
建筑商实体集(“区域”);
builder.EntitySet(“孤儿”);
var products=builder.EntitySet(“产品”);
返回builder.GetEdmModel();
}