Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
262 views
in Technique[技术] by (71.8m points)

c# - OData v4 expand syntax is returns error "...The property 'ProductType' cannot be used in the $expand query option."

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?

enter image description here

// 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found the answer in a post in the odata github issues. issuecomment-248168536 According to this comment this is new behavior in Microsoft.AspNet.OData package version 6.0.0 and is a breaking change. I went back to the other service that was working and checked out the Nuget package and it has v 5.6.0 installed rather than the latest (which is 7.1.0 currently).

So the fix is to add the config line for the features you want before the mapping...

config.Expand().Select();
config.MapODataServiceRoute("odata", null, builder.GetEdmModel());

This is the fix for enabling the option globally to make it work just like the < v6.0 versions. There's a document referenced in that thread (13-01-modelbound-attribute) that demonstrates the new feature of granular control of the options through model attributes.

HTH, Mike


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...