I have a new OData V4 service that I'm trying to get running and I'm seeing the unexpected error...
"The property 'ProductType' cannot be used in the $expand query
option."
I didn't have problems with this in another OData service and I've been comparing the two and I can't find a significant difference between the two WRT the setup of the items in the model and the WebApiConfig. I built this following the example laid out in the article create-an-odata-v4-endpoint whereas the other one was created with a scaffolding wizard.
So here's the layout of the tables, the controllers, and the WebApiConfig. Where else do I look for the reason behind the failure to relate?
// Product.cs
public partial class Product
{
public int ProductId { get; set; }
public int ProductTypeId { get; set; }
public string Size { get; set; }
public string PartNo { get; set; }
public virtual ProductType ProductType { get; set; }
}
// ProductType.cs
public partial class ProductType{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public ProductType()
{
this.Products = new HashSet<Product>();
}
public int ProductTypeId { get; set; }
public string ProductTypeName { get; set; }
public string Image { get; set; }
public string ProductDescription { get; set; }
public string InstallInstructions { get; set; }
public string DataSheet { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Product> Products { get; set; }
}
// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.SetTimeZoneInfo(TimeZoneInfo.Utc);
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
builder.EntityType<Product>().HasKey(entity => entity.ProductId);
builder.EntityType<Product>().HasRequired(entity => entity.ProductType, (entity, targetEntity) => entity.ProductTypeId == targetEntity.ProductTypeId);
builder.EntitySet<ProductType>("ProductTypes");
builder.EntityType<ProductType>().HasKey(entity => entity.ProductTypeId);
builder.EntityType<ProductType>().HasMany(entity => entity.Products);
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
// ProductTypesController.cs
public class ProductTypesController : BaseController
{
[EnableQuery]
public IQueryable<ProductType> Get()
{
return db.ProductTypes;
}
[EnableQuery]
public SingleResult<ProductType> Get([FromODataUri] int key)
{
IQueryable<ProductType> result = db.ProductTypes.Where(p => p.ProductTypeId.Equals(key));
return SingleResult.Create(result);
}
....
}
// ProductsController.cs
public class ProductsController : BaseController
{
[EnableQuery]
public IQueryable<Product> Get()
{
return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
IQueryable<Product> result = db.Products.Where(p => p.ProductId.Equals(key));
return SingleResult.Create(result);
}
...
}
I've tried both directions with of referencing the relate item with singular and multiple selection (typing these urls into the address bar):
/ProductTypes?$expand=Products
, and /ProductTypes(3)?$expand=Products
, and /Products?$expand=ProductType
, and /Products(3)?$expand=ProductType
I get that same error in each case.
If there's something else needed to determine the cause I'll be happy to look it up, I just need to know where to look.
Thanks, Mike
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…