public void CreateModelDescription_SimpleTypes(Type type, string expectedModelName, string expectedDocumentation)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            SimpleTypeModelDescription simpleModel = Assert.IsType<SimpleTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));

            Assert.NotNull(simpleModel);
            Assert.Equal(expectedModelName, simpleModel.Name);
            Assert.Equal(type, simpleModel.ModelType);
            Assert.Equal(expectedDocumentation, simpleModel.Documentation);
        }
        public void CreateModelDescription_Collection(Type collectionType, Type itemType)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            CollectionModelDescription collectionModel = Assert.IsType<CollectionModelDescription>(modelGenerator.GetOrCreateModelDescription(collectionType));

            Assert.NotNull(collectionModel);
            Assert.Equal(collectionType, collectionModel.ModelType);
            Assert.Equal(itemType, collectionModel.ElementDescription.ModelType);
        }
        public void CreateModelDescription_ComplexType_WithDocumentation(Type type, Dictionary<string, string> documentationMapping)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.SetDocumentationProvider(new XmlDocumentationProvider("WebApiHelpPage.Test.XML"));
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            ComplexTypeModelDescription complexModel = Assert.IsType<ComplexTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));

            Assert.NotNull(complexModel);
            Assert.Equal(type, complexModel.ModelType);
            Assert.Equal(documentationMapping.Count, complexModel.Properties.Count);
            foreach (var property in complexModel.Properties)
            {
                string expectedDocumentation = documentationMapping[property.Name];
                Assert.Equal(expectedDocumentation, property.Documentation);
            }
        }
        public void CreateModelDescription_ThrowsOnDuplicateModelName()
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            Assert.Throws<InvalidOperationException>(() =>
            {
                modelGenerator.GetOrCreateModelDescription(typeof(Customer));
                modelGenerator.GetOrCreateModelDescription(typeof(WebApiHelpPageWebHost.UnitTest2.Customer));
            },
            "A model description could not be created. Duplicate model name 'Customer' was found for types 'WebApiHelpPageWebHost.UnitTest.Customer' and 'WebApiHelpPageWebHost.UnitTest2.Customer'. Use the [ModelName] attribute to change the model name for at least one of the types so that it has a unique name.");
        }
        public void CreateModelDescription_ComplexType_ReturnsExpectedModelName(Type type, string expectedModelName)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            ComplexTypeModelDescription complexModel = Assert.IsType<ComplexTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));

            Assert.NotNull(complexModel);
            Assert.Equal(type, complexModel.ModelType);
            Assert.Equal(expectedModelName, complexModel.Name);
        }
        public void CreateModelDescription_ComplexType_WithAnnotation(Type type, Dictionary<string, string[]> annotationMapping)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            ComplexTypeModelDescription complexModel = Assert.IsType<ComplexTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));

            Assert.NotNull(complexModel);
            Assert.Equal(type, complexModel.ModelType);
            Assert.Equal(annotationMapping.Count, complexModel.Properties.Count);
            foreach (var property in complexModel.Properties)
            {
                string[] expectedAnnotations = annotationMapping[property.Name];
                Assert.Equal(expectedAnnotations.Length, property.Annotations.Count);
                for (int i = 0; i < expectedAnnotations.Length; i++)
                {
                    Assert.Equal(expectedAnnotations[i], property.Annotations[i].Documentation);
                }
            }
        }
        public void CreateModelDescription_Enum(Type type, int enumValueCount)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            EnumTypeModelDescription enumModel = Assert.IsType<EnumTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));

            Assert.NotNull(enumModel);
            Assert.Equal(type, enumModel.ModelType);
            Assert.Equal(enumValueCount, enumModel.Values.Count);
        }
        public void CreateModelDescription_ComplexType(Type type, string[] expectedPropertyNames)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            ComplexTypeModelDescription complexModel = Assert.IsType<ComplexTypeModelDescription>(modelGenerator.GetOrCreateModelDescription(type));
            var propertyNames = complexModel.Properties.Select(m => m.Name).ToArray();

            Assert.NotNull(complexModel);
            Assert.Equal(type, complexModel.ModelType);
            Assert.Equal(expectedPropertyNames.Length, propertyNames.Length);
            foreach (var expectedPropertyName in expectedPropertyNames)
            {
                Assert.Contains(expectedPropertyName, propertyNames);
            }
        }
        public void CreateModelDescription_Dictionary(Type dictionaryType, Type keyType, Type valueType)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            DictionaryModelDescription dictionaryModel = Assert.IsType<DictionaryModelDescription>(modelGenerator.GetOrCreateModelDescription(dictionaryType));

            Assert.NotNull(dictionaryModel);
            Assert.Equal(dictionaryType, dictionaryModel.ModelType);
            Assert.Equal(keyType, dictionaryModel.KeyModelDescription.ModelType);
            Assert.Equal(valueType, dictionaryModel.ValueModelDescription.ModelType);
        }
        public void CreateModelDescription_KeyValuePair(Type modelType, Type keyType, Type valueType)
        {
            HttpConfiguration config = new HttpConfiguration();
            ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);

            KeyValuePairModelDescription keyValuePairModel = Assert.IsType<KeyValuePairModelDescription>(modelGenerator.GetOrCreateModelDescription(modelType));

            Assert.NotNull(keyValuePairModel);
            Assert.Equal(modelType, keyValuePairModel.ModelType);
            Assert.Equal(keyType, keyValuePairModel.KeyModelDescription.ModelType);
            Assert.Equal(valueType, keyValuePairModel.ValueModelDescription.ModelType);
        }
 private static ModelDescriptionGenerator InitializeModelDescriptionGenerator(HttpConfiguration config)
 {
     ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);
     Collection<ApiDescription> apis = config.Services.GetApiExplorer().ApiDescriptions;
     foreach (ApiDescription api in apis)
     {
         ApiParameterDescription parameterDescription;
         Type parameterType;
         if (TryGetResourceParameter(api, config, out parameterDescription, out parameterType))
         {
             modelGenerator.GetOrCreateModelDescription(parameterType);
         }
     }
     return modelGenerator;
 }
 private static void GenerateResourceDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
 {
     ResponseDescription response = apiModel.ApiDescription.ResponseDescription;
     Type responseType = response.ResponseType ?? response.DeclaredType;
     if (responseType != null && responseType != typeof(void))
     {
         apiModel.ResourceDescription = modelGenerator.GetOrCreateModelDescription(responseType);
     }
 }
        private static void GenerateRequestModelDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator, HelpPageSampleGenerator sampleGenerator)
        {
            ApiDescription apiDescription = apiModel.ApiDescription;
            foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
            {
                if (apiParameter.Source == ApiParameterSource.FromBody)
                {
                    Type parameterType = apiParameter.ParameterDescriptor.ParameterType;
                    apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
                    apiModel.RequestDocumentation = apiParameter.Documentation;
                }
                else if (apiParameter.ParameterDescriptor != null &&
                    apiParameter.ParameterDescriptor.ParameterType == typeof(HttpRequestMessage))
                {
                    Type parameterType = sampleGenerator.ResolveHttpRequestMessageType(apiDescription);

                    if (parameterType != null)
                    {
                        apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
                    }
                }
            }
        }
        private static void GenerateUriParameters(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
        {
            ApiDescription apiDescription = apiModel.ApiDescription;
            foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
            {
                if (apiParameter.Source == ApiParameterSource.FromUri)
                {
                    HttpParameterDescriptor parameterDescriptor = apiParameter.ParameterDescriptor;
                    Type parameterType = null;
                    ModelDescription typeDescription = null;
                    ComplexTypeModelDescription complexTypeDescription = null;
                    if (parameterDescriptor != null)
                    {
                        parameterType = parameterDescriptor.ParameterType;
                        typeDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
                        complexTypeDescription = typeDescription as ComplexTypeModelDescription;
                    }

                    if (complexTypeDescription != null)
                    {
                        foreach (ParameterDescription uriParameter in complexTypeDescription.Properties)
                        {
                            apiModel.UriParameters.Add(uriParameter);
                        }
                    }
                    else if (parameterDescriptor != null)
                    {
                        ParameterDescription uriParameter =
                            AddParameterDescription(apiModel, apiParameter, typeDescription);

                        if (!parameterDescriptor.IsOptional)
                        {
                            uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Required" });
                        }

                        object defaultValue = parameterDescriptor.DefaultValue;
                        if (defaultValue != null)
                        {
                            uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Default value is " + Convert.ToString(defaultValue, CultureInfo.InvariantCulture) });
                        }
                    }
                    else
                    {
                        Debug.Assert(parameterDescriptor == null);

                        // If parameterDescriptor is null, this is an undeclared route parameter which only occurs
                        // when source is FromUri. Ignored in request model and among resource parameters but listed
                        // as a simple string here.
                        ModelDescription modelDescription = modelGenerator.GetOrCreateModelDescription(typeof(string));
                        AddParameterDescription(apiModel, apiParameter, modelDescription);
                    }
                }
            }
        }
        private static void GenerateUriParameters(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
        {
            ApiDescription apiDescription = apiModel.ApiDescription;
            foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
            {
                if (apiParameter.Source == ApiParameterSource.FromUri)
                {
                    HttpParameterDescriptor parameterDescriptor = apiParameter.ParameterDescriptor;
                    Type parameterType = null;
                    ModelDescription typeDescription = null;
                    ComplexTypeModelDescription complexTypeDescription = null;
                    if (parameterDescriptor != null)
                    {
                        parameterType = parameterDescriptor.ParameterType;
                        typeDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
                        complexTypeDescription = typeDescription as ComplexTypeModelDescription;
                    }

                    // Example:
                    // [TypeConverter(typeof(PointConverter))]
                    // public class Point
                    // {
                    //     public Point(int x, int y)
                    //     {
                    //         X = x;
                    //         Y = y;
                    //     }
                    //     public int X { get; set; }
                    //     public int Y { get; set; }
                    // }
                    // Class Point is bindable with a TypeConverter, so Point will be added to UriParameters collection.
                    // 
                    // public class Point
                    // {
                    //     public int X { get; set; }
                    //     public int Y { get; set; }
                    // }
                    // Regular complex class Point will have properties X and Y added to UriParameters collection.
                    if (complexTypeDescription != null
                        && !IsBindableWithTypeConverter(parameterType))
                    {
                        foreach (ParameterDescription uriParameter in complexTypeDescription.Properties)
                        {
                            apiModel.UriParameters.Add(uriParameter);
                        }
                    }
                    else if (parameterDescriptor != null)
                    {
                        ParameterDescription uriParameter =
                            AddParameterDescription(apiModel, apiParameter, typeDescription);

                        if (!parameterDescriptor.IsOptional)
                        {
                            uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Required" });
                        }

                        object defaultValue = parameterDescriptor.DefaultValue;
                        if (defaultValue != null)
                        {
                            uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Default value is " + Convert.ToString(defaultValue, CultureInfo.InvariantCulture) });
                        }
                    }
                    else
                    {
                        Debug.Assert(parameterDescriptor == null);

                        // If parameterDescriptor is null, this is an undeclared route parameter which only occurs
                        // when source is FromUri. Ignored in request model and among resource parameters but listed
                        // as a simple string here.
                        ModelDescription modelDescription = modelGenerator.GetOrCreateModelDescription(typeof(string));
                        AddParameterDescription(apiModel, apiParameter, modelDescription);
                    }
                }
            }
        }