OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
857 stars 473 forks source link

When adding an EntitySet to ODataConventionModelBuilder using a complex heirarchical type, some downstream types are not "picked up" and must be added to the builder manually. #579

Closed nickkin-msft closed 8 years ago

nickkin-msft commented 8 years ago

You can use the same repro zip I sent WRT https://github.com/OData/WebApi/issues/575 to repro this as well. Simply comment out lines 46 and 47 in WebApiConfig.cs:

        // somehow the builder doesn't pick up on these xsd generated enums??? (it finds the rest just fine...)
        <snip>builder.AddEnumType(typeof(<snip>.DeviceType));
        <snip>builder.AddEnumType(typeof(<snip>.Architecture));

Then run.

This is non-blocking since I do have the above workaround, and AFAIK is not a regression, so its not high-pri (and thanks again for looking into 575 so quickly!)

Full exception / stack trace (I used a local build that includes the fix for issue 575):

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

     Exception Details: System.InvalidOperationException: The enum type 'DeviceType' does not exist.

    Source Error: 

    Line 219:                if (edmType == null)
    Line 220:                {
    Line 221:                    throw Error.InvalidOperation(SRResources.EnumTypeDoesNotExist, clrType.Name);
    Line 222:                }
    Line 223:

     Source File:  c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs    Line:  221 

    Stack Trace: 

    [InvalidOperationException: The enum type 'DeviceType' does not exist.]
       System.Web.OData.Builder.EdmTypeBuilder.CreateStructuralTypeCollectionPropertyBody(EdmStructuredType type, CollectionPropertyConfiguration collectionProperty) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:221
       System.Web.OData.Builder.EdmTypeBuilder.CreateStructuralTypeBody(EdmStructuredType type, StructuralTypeConfiguration config) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:184
       System.Web.OData.Builder.EdmTypeBuilder.CreateComplexTypeBody(EdmComplexType type, ComplexTypeConfiguration config) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:282
       System.Web.OData.Builder.EdmTypeBuilder.CreateEdmTypeBody(IEdmTypeConfiguration config) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:133
       System.Web.OData.Builder.EdmTypeBuilder.GetEdmTypes() in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:51
       System.Web.OData.Builder.EdmTypeBuilder.GetTypesAndProperties(IEnumerable`1 configurations) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmTypeBuilder.cs:423
       System.Web.OData.Builder.EdmModelHelperMethods.BuildEdmModel(ODataModelBuilder builder) in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\EdmModelHelperMethods.cs:33
       System.Web.OData.Builder.ODataModelBuilder.GetEdmModel() in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\ODataModelBuilder.cs:590
       System.Web.OData.Builder.ODataConventionModelBuilder.GetEdmModel() in c:\dev\WebApi2\OData\src\System.Web.OData\OData\Builder\ODataConventionModelBuilder.cs:280
       ODataRegressionRepro.WebApiConfig.Register(HttpConfiguration config) in c:\Users\nickkin\Documents\Visual Studio 2013\Projects\ODataRegressionRepro\ODataRegressionRepro\App_Start\WebApiConfig.cs:50
       System.Web.Http.GlobalConfiguration.Configure(Action`1 configurationCallback) +125
       ODataRegressionRepro.WebApiApplication.Application_Start() in c:\Users\nickkin\Documents\Visual Studio 2013\Projects\ODataRegressionRepro\ODataRegressionRepro\Global.asax.cs:14

    [HttpException (0x80004005): The enum type 'DeviceType' does not exist.]
       System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +9941577
       System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +118
       System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +172
       System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +339
       System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +296

    [HttpException (0x80004005): The enum type 'DeviceType' does not exist.]
       System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9923088
       System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +90
       System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +261

Thanks, Nick

nickkin-msft commented 8 years ago

Sent internal email with the repro zip again, just in case.

xuzhg commented 8 years ago

Convention model builder will go through all related 'types' starting from the explicitly configured 'types'. So, please make sure 'DeviceType' can be accessed from one of explicitly configured 'types. Otherwise, you should call AddEnumType Fluent API to explicitly add the enum type into model.

nickkin-msft commented 8 years ago

Yes, that's the bug. The type is referenced indirectly (a->b->c etc.) from the root entity type that is being configured, however when hitting the endpoint it throws the exception because the builder didn't "find" it. Thus I have to add it manually. For the XSD generated classes I'm using, its the enums DeviceType and Architecture (but other indirectly referenced enums are found.)

xuzhg commented 8 years ago

It’s a bug that we only cover the IEnumerable where T : enum, doesn’t cover the T[] where T: enum. PR is out for fix. Thanks.

VikingsFan commented 8 years ago

PR #582 Merged 8b99db1a012c7931bba3e668f271d8aed61c215c