具有 OWIN 自托管的 Web API 无类型 OData 服务返回 406 Not Acceptable
Posted
技术标签:
【中文标题】具有 OWIN 自托管的 Web API 无类型 OData 服务返回 406 Not Acceptable【英文标题】:Web API Typeless OData Service with OWIN self-hosting returns 406 Not Acceptable 【发布时间】:2014-05-12 18:11:52 【问题描述】:我正在尝试使用 OWIN 自托管设置 Web API 无类型 OData 服务... =)
但为什么不工作? :~(
这是我从各种示例中部分提取的一些代码...
public class Startup
public void Configuration(IAppBuilder appBuilder)
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/controller/id",
new id = RouteParameter.Optional );
appBuilder.UseWebApi(config);
public class Program
public static IEdmModel Model = GetEdmModel();
static void Main(string[] args)
using (WebApp.Start<Startup>("http://localhost:8080"))
Console.WriteLine("Running...");
Console.ReadLine();
public static IEdmModel GetEdmModel()
var model = new EdmModel();
// Create and add product entity type.
var product = new EdmEntityType("NS", "Product");
product.AddKeys(product.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
product.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
product.AddStructuralProperty("Price", EdmPrimitiveTypeKind.Double);
model.AddElement(product);
// Create and add category entity type.
var category = new EdmEntityType("NS", "Category");
category.AddKeys(category.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
category.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
model.AddElement(category);
// Set navigation from product to category.
var propertyInfo = new EdmNavigationPropertyInfo();
propertyInfo.Name = "Category";
propertyInfo.TargetMultiplicity = EdmMultiplicity.One;
propertyInfo.Target = category;
var productCategory = product.AddUnidirectionalNavigation(propertyInfo);
// Create and add entity container.
var container = new EdmEntityContainer("NS", "DefaultContainer");
model.AddElement(container);
// Create and add entity set for product and category.
var products = container.AddEntitySet("Products", product);
var categories = container.AddEntitySet("Categories", category);
products.AddNavigationTarget(productCategory, categories);
return model;
public class ProductsController : ODataController
private static readonly IQueryable<IEdmEntityObject> Products = Enumerable.Range(0, 10).Select(i =>
var productType = (IEdmEntityType)Program.Model.FindType("NS.Product");
var categoryType = (IEdmEntityTypeReference)productType.FindProperty("Category").Type;
var product = new EdmEntityObject(productType);
product.TrySetPropertyValue("Id", i);
product.TrySetPropertyValue("Name", "Product " + i);
product.TrySetPropertyValue("Price", i + 0.01);
var category = new EdmEntityObject(categoryType);
category.TrySetPropertyValue("Id", i % 5);
category.TrySetPropertyValue("Name", "Category " + (i % 5));
product.TrySetPropertyValue("Category", category);
return product;
).AsQueryable();
public EdmEntityObjectCollection Get()
// Get Edm type from request.
var path = this.Request.GetODataPath();
var edmType = path.EdmType;
Contract.Assert(edmType.TypeKind == EdmTypeKind.Collection);
var collectionType = edmType as IEdmCollectionType;
var entityType = collectionType.ElementType.Definition as IEdmEntityType;
var model = Request.GetEdmModel();
var queryContext = new ODataQueryContext(model, entityType);
var queryOptions = new ODataQueryOptions(queryContext, Request);
// Apply the query option on the IQueryable here.
return new EdmEntityObjectCollection(new EdmCollectionTypeReference(collectionType, false), Products.ToList());
public IEdmEntityObject GetProduct(int key)
object id;
var product = Products.Single(p => HasId(p, key));
return product;
public IEdmEntityObject GetCategoryFromProduct(int key)
object id;
var product = Products.Single(p => HasId(p, key));
object category;
if (product.TryGetPropertyValue("Category", out category))
return (IEdmEntityObject)category;
return null;
public IEdmEntityObject Post(IEdmEntityObject entity)
// Get Edm type from request.
var path = Request.GetODataPath();
var edmType = path.EdmType;
Contract.Assert(edmType.TypeKind == EdmTypeKind.Collection);
var entityType = (edmType as IEdmCollectionType).ElementType.AsEntity();
// Do something with the entity object here.
return entity;
private bool HasId(IEdmEntityObject product, int key)
object id;
return product.TryGetPropertyValue("Id", out id) && (int)id == key;
我得到的结果是:
StatusCode: 406, ReasonPhrase: 'Not Acceptable', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
Date: Mon, 12 May 2014 18:08:25 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 0
从运行这个:
var client = new HttpClient();
var response = client.GetAsync("http://localhost:8080/api/Products").Result;
【问题讨论】:
尝试使用 config.MapODataServiceRoute(...) 方法映射 OData 路由。 【参考方案1】:如果您使用的是 OData V4,则需要在控制器中进行更改: 老:
using System.Web.Http.OData;
新:
using System.Web.OData;
【讨论】:
以上是关于具有 OWIN 自托管的 Web API 无类型 OData 服务返回 406 Not Acceptable的主要内容,如果未能解决你的问题,请参考以下文章
具有 OWIN 自主机和 Windows 身份验证的 Web Api
asp.net web api 自托管 / owin / katana
在 DELETE 上不允许使用 Owin 自托管 Web API 405 方法
在使用 Owin 自托管的 Web API 中获取远程主机 IP