Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API 2 OData EDM Anomaly

I have the following code:

public class AwardTitle
{
    public int AwardTitleId
    {
        get;
        set;
    }

    public int? EpisodeId
    {
        get;
        set;
    }

    public virtual AwardEpisode Episode
    {
        get;
        set;
    }
}

public class AwardEpisode
{
    public int EpisodeId
    {
        get;
        set;
    }
}

public static class WebApiConfig
{
    public static void Register( HttpConfiguration config )
    {
        config.Routes.MapODataRoute( "ODataRoute", "api", GetImplicitEDM( ) );
    }
}

private static Microsoft.Data.Edm.IEdmModel GetImplicitEDM( )
{
    var builder = new ODataConventionModelBuilder( );
    builder.EntitySet<AwardTitle>( "AwardTitles" );

    return builder.GetEdmModel( );
}

Notice how I have only mapped the AwardTitle class... not the AwardEpisode class.

Now, when I browse to the controller, I would expect to get an error about not having AwardEpisode mapped. However, there is no error. In fact, in addition to AwardTitle being retrieved... AwardEpisode is also being retrieved... without any explicit calls to do so.

How is this possible??? Should this be possible??

I'm using ASP.Net Web API 2 on Windows 7.

like image 242
Chris Avatar asked Jan 01 '26 09:01

Chris


1 Answers

ODataConventionModelBuilder by default map a type T's primitive, complex, and navigation properties for the .EntitySet<TEntityType>(string name) api call. The code is:

private void MapEntityType(EntityTypeConfiguration entity)
{
    IEnumerable<PropertyInfo> properties = ConventionsHelpers.GetProperties(entity, includeReadOnly: _isQueryCompositionMode);
    foreach (PropertyInfo property in properties)
    {
        bool isCollection;
        StructuralTypeConfiguration mappedType;

        PropertyKind propertyKind = GetPropertyType(property, out isCollection, out mappedType);

        if (propertyKind == PropertyKind.Primitive || propertyKind == PropertyKind.Complex)
        {
            MapStructuralProperty(entity, property, propertyKind, isCollection);
        }
        else
        {
            // don't add this property if the user has already added it.
            if (!entity.NavigationProperties.Where(p => p.Name == property.Name).Any())
            {
                NavigationPropertyConfiguration addedNavigationProperty;
                if (!isCollection)
                {
                    addedNavigationProperty = entity.AddNavigationProperty(property, EdmMultiplicity.ZeroOrOne);
                }
                else
                {
                    addedNavigationProperty = entity.AddNavigationProperty(property, EdmMultiplicity.Many);
                }

                addedNavigationProperty.AddedExplicitly = false;
            }
        }
    }

An example of the test case:

public void ModelBuilder_Products()
{
    var modelBuilder = new ODataConventionModelBuilder();
    modelBuilder.EntitySet<Product>("Products");

    var model = modelBuilder.GetEdmModel();

    var product = model.AssertHasEntitySet(entitySetName: "Products", mappedEntityClrType: typeof(Product));
    product.AssertHasPrimitiveProperty(model, "ReleaseDate", EdmPrimitiveTypeKind.DateTime, isNullable: true);
    product.AssertHasComplexProperty(model, "Version", typeof(ProductVersion), isNullable: true);
    product.AssertHasNavigationProperty(model, "Category", typeof(Category), isNullable: true, multiplicity: EdmMultiplicity.ZeroOrOne);

To change the default behavior, we can ignore the property:

var builder = new ODataConventionModelBuilder();
builder.Entity<AwardTitle>().Ignore(a => a.Episode);
builder.EntitySet<AwardTitle>("AwardTitles");

return builder.GetEdmModel();
like image 189
Congyong Su Avatar answered Jan 04 '26 19:01

Congyong Su



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!