具有OWIN自托管的Web API无类型OData服务返回406不可接受

时间:2014-05-12 18:11:53

标签: asp.net httpclient asp.net-web-api owin

我尝试使用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;

1 个答案:

答案 0 :(得分:2)

如果您使用的是OData V4,则需要在控制器中进行更改:
老:

using System.Web.Http.OData;

新:

using System.Web.OData;