public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead)
        {
            // Arrange
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes("content");

            var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
            var formatterContext = new InputFormatterContext(actionContext, typeof(string));

            // Act
            var result = formatter.CanRead(formatterContext);

            // Assert
            Assert.Equal(expectedCanRead, result);
        }
        public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead)
        {
            // Arrange
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes("content");

            var modelState = new ModelStateDictionary();
            var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
            var formatterContext = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                modelType: typeof(string));

            // Act
            var result = formatter.CanRead(formatterContext);

            // Assert
            Assert.Equal(expectedCanRead, result);
        }
Example #3
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.Configure <MvcOptions>(options =>
            {
                options.InputFormatters.Clear();

                var jsonInputFormatter = new JsonInputFormatter();
                jsonInputFormatter.SupportedMediaTypes.Clear();
                jsonInputFormatter.SupportedMediaTypes.Add(JsonMediaType);
                options.InputFormatters.Add(jsonInputFormatter);

                var xmlSerializerInputFormatter = new XmlSerializerInputFormatter();
                xmlSerializerInputFormatter.SupportedMediaTypes.Clear();
                xmlSerializerInputFormatter.SupportedMediaTypes.Add(XmlSerializerMediaType);
                options.InputFormatters.Add(xmlSerializerInputFormatter);

                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Clear();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add(XmlDataContractSerializerMediaType);
                options.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                options.OutputFormatters.Clear();

                var jsonOutputFormatter = new JsonOutputFormatter();
                jsonOutputFormatter.SupportedMediaTypes.Clear();
                jsonOutputFormatter.SupportedMediaTypes.Add(JsonMediaType);
                options.OutputFormatters.Add(jsonOutputFormatter);

                var xmlSerializerOutputFormatter = new XmlSerializerOutputFormatter();
                xmlSerializerOutputFormatter.SupportedMediaTypes.Clear();
                xmlSerializerOutputFormatter.SupportedMediaTypes.Add(XmlSerializerMediaType);
                options.OutputFormatters.Add(xmlSerializerOutputFormatter);

                var xmlDataContractSerializerOutputFormatter = new XmlDataContractSerializerOutputFormatter();
                xmlDataContractSerializerOutputFormatter.SupportedMediaTypes.Clear();
                xmlDataContractSerializerOutputFormatter.SupportedMediaTypes.Add(XmlDataContractSerializerMediaType);
                options.OutputFormatters.Add(xmlDataContractSerializerOutputFormatter);
            });
        }
Example #4
0
    public async Task SuppressInputFormatterBufferingSetToTrue_UsingMutatedOptions()
    {
        // Arrange
        var expectedInt    = 10;
        var expectedString = "TestString";

        var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<TestLevelOne><SampleInt>" + expectedInt + "</SampleInt>" +
                    "<sampleString>" + expectedString + "</sampleString></TestLevelOne>";

        var mvcOptions = new MvcOptions()
        {
            SuppressInputFormatterBuffering = false
        };
        var formatter    = new XmlDataContractSerializerInputFormatter(mvcOptions);
        var contentBytes = Encoding.UTF8.GetBytes(input);
        var httpContext  = new DefaultHttpContext();

        httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature());
        httpContext.Request.Body        = new NonSeekableReadStream(contentBytes);
        httpContext.Request.ContentType = "application/xml";
        var context = GetInputFormatterContext(httpContext, typeof(TestLevelOne));

        // Act
        // Mutate options after passing into the constructor to make sure that the value type is not store in the constructor
        mvcOptions.SuppressInputFormatterBuffering = true;
        var result = await formatter.ReadAsync(context);

        // Assert
        Assert.NotNull(result);
        Assert.False(result.HasError);
        var model = Assert.IsType <TestLevelOne>(result.Model);

        Assert.Equal(expectedInt, model.SampleInt);
        Assert.Equal(expectedString, model.sampleString);

        // Reading again should fail as buffering request body is disabled
        await Assert.ThrowsAsync <XmlException>(() => formatter.ReadAsync(context));
    }
Example #5
0
    public async Task ReadAsync_ReadsWhenConfiguredWithKnownTypes()
    {
        // Arrange
        var expectedInt       = 10;
        var expectedString    = "TestString";
        var KnownTypeName     = "SomeDummyClass";
        var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";

        var input = string.Format(
            CultureInfo.InvariantCulture,
            "<DummyClass i:type=\"{0}\" xmlns:i=\"{1}\"><SampleInt>{2}</SampleInt>"
            + "<SampleString>{3}</SampleString></DummyClass>",
            KnownTypeName,
            InstanceNamespace,
            expectedInt,
            expectedString);
        var settings = new DataContractSerializerSettings
        {
            KnownTypes = new[] { typeof(SomeDummyClass) }
        };
        var formatter = new XmlDataContractSerializerInputFormatter(new MvcOptions())
        {
            SerializerSettings = settings
        };
        var contentBytes = Encoding.UTF8.GetBytes(input);
        var context      = GetInputFormatterContext(contentBytes, typeof(DummyClass));

        // Act
        var result = await formatter.ReadAsync(context);

        // Assert
        Assert.NotNull(result);
        Assert.False(result.HasError);
        var model = Assert.IsType <SomeDummyClass>(result.Model);

        Assert.Equal(expectedInt, model.SampleInt);
        Assert.Equal(expectedString, model.SampleString);
    }
Example #6
0
    public async Task ReadAsync_ReadsWhenMaxDepthIsModified()
    {
        // Arrange
        var expectedInt = 10;

        var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<DummyClass><SampleInt>" + expectedInt + "</SampleInt></DummyClass>";
        var formatter = new XmlDataContractSerializerInputFormatter(new MvcOptions());

        formatter.MaxDepth = 10;
        var contentBytes = Encoding.UTF8.GetBytes(input);
        var context      = GetInputFormatterContext(contentBytes, typeof(DummyClass));

        // Act
        var result = await formatter.ReadAsync(context);

        // Assert
        Assert.NotNull(result);
        Assert.False(result.HasError);
        var model = Assert.IsType <DummyClass>(result.Model);

        Assert.Equal(expectedInt, model.SampleInt);
    }
        public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead)
        {
            // Arrange
            var formatter    = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes("content");

            var modelState       = new ModelStateDictionary();
            var httpContext      = GetHttpContext(contentBytes, contentType: requestContentType);
            var provider         = new EmptyModelMetadataProvider();
            var metadata         = provider.GetMetadataForType(typeof(string));
            var formatterContext = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                metadata: metadata,
                readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader);

            // Act
            var result = formatter.CanRead(formatterContext);

            // Assert
            Assert.Equal(expectedCanRead, result);
        }
        public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead)
        {
            // Arrange
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes("content");

            var modelState = new ModelStateDictionary();
            var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
            var provider = new EmptyModelMetadataProvider();
            var metadata = provider.GetMetadataForType(typeof(string));
            var formatterContext = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                metadata: metadata,
                readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader);

            // Act
            var result = formatter.CanRead(formatterContext);

            // Assert
            Assert.Equal(expectedCanRead, result);
        }
Example #9
0
        private void ConfigureOutputFormatters(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                // Add XML Data contract serializer
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            }).AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });
        }
Example #10
0
    public async Task ReadAsync_ReadsWhenConfiguredWithRootName()
    {
        // Arrange
        var expectedInt             = 10;
        var SubstituteRootName      = "SomeOtherClass";
        var SubstituteRootNamespace = "http://tempuri.org";

        var input = string.Format(
            CultureInfo.InvariantCulture,
            "<{0} xmlns=\"{1}\"><SampleInt xmlns=\"\">{2}</SampleInt></{0}>",
            SubstituteRootName,
            SubstituteRootNamespace,
            expectedInt);

        var dictionary = new XmlDictionary();
        var settings   = new DataContractSerializerSettings
        {
            RootName      = dictionary.Add(SubstituteRootName),
            RootNamespace = dictionary.Add(SubstituteRootNamespace)
        };
        var formatter = new XmlDataContractSerializerInputFormatter(new MvcOptions())
        {
            SerializerSettings = settings
        };
        var contentBytes = Encoding.UTF8.GetBytes(input);
        var context      = GetInputFormatterContext(contentBytes, typeof(DummyClass));

        // Act
        var result = await formatter.ReadAsync(context);

        // Assert
        Assert.NotNull(result);
        Assert.False(result.HasError);
        var model = Assert.IsType <DummyClass>(result.Model);

        Assert.Equal(expectedInt, model.SampleInt);
    }
        private static void SetupMvcOptions(MvcOptions setupAction)
        {
            setupAction.ReturnHttpNotAcceptable = true;
            setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

            XmlDataContractSerializerInputFormatter xmlDataContractSerializerInputFormatter =
                new XmlDataContractSerializerInputFormatter();

            xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add(
                "application/vnd.marvin.authorwithdateofdeath.full+xml");

            setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

            JsonOutputFormatter jsonOutputFormatter =
                setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();

            jsonOutputFormatter?.SupportedMediaTypes.Add(VendorMediaType);

            JsonInputFormatter jsonInputFormatter =
                setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();

            jsonInputFormatter?.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
            jsonInputFormatter?.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");
        }
        public async Task ReadAsync_AcceptsUTF16Characters()
        {
            // Arrange
            var expectedInt    = 10;
            var expectedString = "TestString";

            var input = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
                        "<TestLevelOne><SampleInt>" + expectedInt + "</SampleInt>" +
                        "<sampleString>" + expectedString + "</sampleString></TestLevelOne>";

            var formatter    = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.Unicode.GetBytes(input);

            var modelState  = new ModelStateDictionary();
            var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");

            var provider = new EmptyModelMetadataProvider();
            var metadata = provider.GetMetadataForType(typeof(TestLevelOne));
            var context  = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                metadata: metadata,
                readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader);

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType <TestLevelOne>(result.Model);

            Assert.Equal(expectedInt, model.SampleInt);
            Assert.Equal(expectedString, model.sampleString);
        }
        public async Task PostingModelOfStructs_WithDeeperHierarchy_HasValidationErrors()
        {
            // Arrange
            var input = "<School i:nil=\"true\" " +
                "xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\" " +
                "xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"/>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(School));

            // Act
            var model = await formatter.ReadAsync(context);

            // Assert
            Assert.Null(model);

            Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(School).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(School.Id), typeof(School).FullName)
                });
            AssertModelStateErrorMessages(
                typeof(Website).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Website.Id), typeof(Website).FullName)
                });

            AssertModelStateErrorMessages(
                typeof(Student).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Student.Id), typeof(Student).FullName)
                });
        }
Example #14
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(
                setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;                                       // Force consumer to specify data format
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); // Support returning XML
                setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());   // Support incoming XML

                // Versioning support for date of demise with XML
                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.companywithdateofdemise.full+xml");
                // Don't bother adding support for XML for v3

                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                // Versioning support for date of demise with JSON
                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.company.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.companywithdateofdemise.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.companywithlocation.full+json");
                }

                // Use custom media type to support HATEOAS
                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            }).AddJsonOptions(
                options =>
            {
                // Prevent property name casing from being lost on serialization of JSON requests
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // Approach using a DB Context (for fast development).
            // https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/
            // Add-Migration InitialCreate or dotnet ef migrations add InitialCreate
            // Update-Database or dotnet ef database update
            // Add-Migration AddDateOfDemise or dotnet ef migrations add AddDateOfDemise
            // TODO - Move connection string to environment variable
            var connectionString = Configuration["connectionStrings:dbConnectionString"];

            services.AddDbContext <RepositoryContext>(context => context.UseSqlServer(connectionString));

            //services.AddScoped<IRepository, MockRepository>();
            services.AddScoped <IRepository, EntityFrameworkRepository>();

            // Register URI helper to support metadata in responses
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper, UrlHelper>(
                implementationFactory =>
            {
                return(new UrlHelper(actionContext: implementationFactory.GetService <IActionContextAccessor>().ActionContext));
            });


            services.AddTransient <IPropertyMappingService, PropertyMappingService>();  // Custom service to support sorting
            services.AddTransient <ITypeHelperService, TypeHelperService>();            // Custom service to support data shaping

            // Caching support for consumer using HTTP cache headers from Marvin
            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                => { expirationModelOptions.MaxAge = 600; },           // expiration caching
                (validationModelOptions)
                => { validationModelOptions.MustRevalidate = true; }); // validation caching

            services.AddResponseCaching();                             // MS .Net core package for response caching. Doesn't generate response headers. Buggy before v2. Not ideal!

            // Implement throttling
            // Can throttle by IP and / or by client.
            // Can throttle by calls to specific controllers or methods
            // Can throttle by (for example); requests per day, requests per hour, and requests per controller.
            // Request headers for this are; X-Rate-Limit-Limit, X-Rate-Limit-Remaining, and X-Rate-Limit-Reset.
            // Disallowed requests will return a 429 response with an optional Retry-After header and a body explaining the condition.

            services.AddMemoryCache();             // Used to store throttling counters and rules

            services.Configure <IpRateLimitOptions>(
                options =>
            {
                options.GeneralRules = new List <RateLimitRule>
                {
                    new RateLimitRule                             // 10 requests every 5 minutes
                    {
                        Endpoint = "*",
                        Limit    = 10,
                        Period   = "5m"
                    },
                    new RateLimitRule                             // 2 requests every 10 seconds
                    {
                        Endpoint = "*",
                        Limit    = 2,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
        public void HasProperSuppportedEncodings()
        {
            // Arrange & Act
            var formatter = new XmlDataContractSerializerInputFormatter();

            // Assert
            Assert.True(formatter.SupportedEncodings.Any(i => i.WebName == "utf-8"));
            Assert.True(formatter.SupportedEncodings.Any(i => i.WebName == "utf-16"));
        }
        public async Task PostingModelInheritingType_HasRequiredAttributeValidationErrors()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<ModelInheritingTypeHavingRequiredAttributeValidationErrors" +
                " xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
                "<IsResidential>true</IsResidential><Zipcode>98052</Zipcode>" +
                "</ModelInheritingTypeHavingRequiredAttributeValidationErrors>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(
                contentBytes,
                typeof(ModelInheritingTypeHavingRequiredAttributeValidationErrors));

            // Act
            var model = await formatter.ReadAsync(context)
                as ModelInheritingTypeHavingRequiredAttributeValidationErrors;

            // Assert
            Assert.NotNull(model);
            Assert.Equal(98052, model.Zipcode);
            Assert.Equal(true, model.IsResidential);

            Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Address).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName)
                });
        }
Example #17
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction => {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());   //  Accept : application/xml
                                                                                                    //setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());     //  Content-Type: application/xml

                #region Register XML Input Formatter for new media type
                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);
                #endregion

                #region Registering Input Formatter Media Links

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }
                #endregion

                #region Registering Custom Content Negotiation for Output Formatters => Accept : application/vnd.marvin.hateoas+json
                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
                #endregion
            })
            // LOWERCASING  =>   CamelCase
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];
            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            #region Register Repository Pattern

            services.AddScoped <ILibraryRepository, LibraryRepository>();

            #endregion

            #region Property Mapping Service for Sorting Data

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            #endregion

            #region Shape Resources e.g. http://localhost:6058/api/authors?fields=id i.e. Dynamically Mapping AuthorDTO properties to Entity.Author for Data Shaping on the Controller Actions that do not support Dynamic Sorting

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            #endregion

            #region Generate URIs to previous and next page for PAGINATION

            // UrlHelper requires context in which the action (IActionHelper => GET / POST / DELETE / PUT / PATCH / .. etc) runs
            // Initiate first time its requested
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            // UrlHelper will generate URIs to an action (IActionHelper => GET / POST / DELETE / PUT / PATCH / .. etc)
            // .AddScoped is used so an instance is created once per request
            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });
            #endregion

            #region HTTP Cache Header Middleware => Marvin.Cache.Headers    => ETags in Response Headers are used

            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                =>
            {
                expirationModelOptions.MaxAge = 600;
            },
                (validationModelOptions)
                =>
            {
                validationModelOptions.AddMustRevalidate = true;
            });

            #endregion

            //  microsoft.aspnetcore.responsecaching => Response caching relating services  => ETags in Response Headers are used
            services.AddResponseCaching();

            #region Rate Limiting and Throttling => How Many Requests per Minute/Hour/etc.

            // registering service
            services.AddMemoryCache();

            //  AspNetCoreRateLimit => 3rd part NuGet to configure limiting
            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 10,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 2,
                        Period   = "10s"
                    }
                };
            });
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();

            #endregion
        }
        public async Task PostingModel_WithDictionaryProperty_HasValidationErrorsOnKeyAndValue()
        {
            // Arrange
            var input = "<FavoriteLocations " +
                "i:nil=\"true\" xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"/>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(FavoriteLocations));

            // Act
            var model = await formatter.ReadAsync(context);

            // Assert
            Assert.Null(model);

            Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Point).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Point.Y), typeof(Point).FullName)
                });
            AssertModelStateErrorMessages(
                typeof(Address).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName)
                });
        }
        public async Task PostingModel_WithPropertyHavingNullableValueTypes_NoRequiredAttributeValidationErrors()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<ModelWithPropertyHavingTypeWithNullableProperties " +
                "xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\" " +
                "xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><CarInfoProperty>" +
                "<ServicedYears xmlns:a=\"http://schemas.datacontract.org/2004/07/System\"><a:int>2006</a:int>" +
                "<a:int>2007</a:int></ServicedYears><Year>2005</Year></CarInfoProperty>" +
                "</ModelWithPropertyHavingTypeWithNullableProperties>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(
                contentBytes,
                typeof(ModelWithPropertyHavingTypeWithNullableProperties));
            var expectedModel = new ModelWithPropertyHavingTypeWithNullableProperties()
            {
                CarInfoProperty = new CarInfo() { Year = 2005, ServicedYears = new List<int?>() }
            };

            expectedModel.CarInfoProperty.ServicedYears.Add(2006);
            expectedModel.CarInfoProperty.ServicedYears.Add(2007);

            // Act
            var model = await formatter.ReadAsync(context) as ModelWithPropertyHavingTypeWithNullableProperties;

            // Assert
            Assert.NotNull(model);
            Assert.NotNull(model.CarInfoProperty);
            Assert.Equal(expectedModel.CarInfoProperty.Year, model.CarInfoProperty.Year);
            Assert.Equal(expectedModel.CarInfoProperty.ServicedYears, model.CarInfoProperty.ServicedYears);
            Assert.Empty(context.ActionContext.ModelState);
        }
Example #20
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext <LibraryContext>(opt => opt.UseInMemoryDatabase("Library"));
            services.AddScoped <ILibraryRepository, LibraryRepository>();
            services.AddMvc(opt =>
            {
                opt.ReturnHttpNotAcceptable = true;
                opt.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                opt.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var jsonOutputFormatter = opt.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.hateoas+json");
                    jsonOutputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                    jsonOutputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });
            services.AddResponseCaching();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();
            services.AddHttpCacheHeaders((expirationModelOptions) =>
            {
                expirationModelOptions.MaxAge = 600;
            }, (validationModelOptions) =>
            {
                validationModelOptions.AddMustRevalidate = true;
            });

            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
        public async Task PostingListOfModels_WithRequiredAndDataMemberNoRequired_HasValidationErrors()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                        "<ArrayOfProduct xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                        " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Product><Id>" +
                        "10</Id><Name>Phone</Name></Product></ArrayOfProduct>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(List<Product>));

            // Act
            var model = await formatter.ReadAsync(context) as List<Product>;

            // Assert
            Assert.NotNull(model);
            Assert.Equal(1, model.Count);
            Assert.Equal(10, model[0].Id);
            Assert.Equal("Phone", model[0].Name);

            Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Product).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
                });

            AssertModelStateErrorMessages(
                typeof(Address).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName)
                });
        }
Example #22
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction => {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();

                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.owpini.full+xml");

                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.owpini.business.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.owpini.hateoas+json");
                }
            })
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            services.AddDbContext <OwpiniDbContext>(options =>
                                                    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity <OwpiniUser, IdentityRole>()
            .AddEntityFrameworkStores <OwpiniDbContext>()
            .AddDefaultTokenProviders();

            services.AddResponseCaching();

            services.AddSwaggerGen(setupAction =>
            {
                setupAction.SwaggerDoc("OwpiniApi",
                                       new Info {
                    Title = "Owpini API Documentation"
                });
            });


            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddScoped <IOwpiniRepository, OwpiniRepository>();
            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();
        }
Example #23
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => {
                // Return a 406 when an unsupported media type was requested
                options.ReturnHttpNotAcceptable = true;

                // Add XML formatters
                options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(options));
                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.ifeanyi.authorwithdateofdeath.full+xml");
                options.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = options.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.ifeanyi.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.ifeanyi.authorwithdateofdeath.full+json");
                }
                var jsonOutputFormatter = options.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.ifeanyi.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper>(implementationFactory => {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // Caching middleware
            services.AddHttpCacheHeaders((expirationModelOptions) => { expirationModelOptions.MaxAge = 600; },
                                         (validationModelOptions) => { validationModelOptions.AddMustRevalidate = true; });

            //services.AddResponseCaching();
            services.AddMemoryCache();

            //Rate limit middleware
            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
Example #24
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            services.AddResponseCaching();

            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            services.AddHttpCacheHeaders(exp => {
                exp.MaxAge = 30;
            }, vald => {
                vald.MustRevalidate = true;
            });
        }
Example #25
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;

                // Add XML Output Formatter
                var xmlDataContractSerializerOutputFormatter = new XmlDataContractSerializerOutputFormatter();
                xmlDataContractSerializerOutputFormatter.SupportedMediaTypes.Add("application/vnd.nagarro.hateoas+xml");
                setupAction.OutputFormatters.Add(xmlDataContractSerializerOutputFormatter);

                // Add XML Input Formatter
                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter(setupAction);
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.nagarro.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(setupAction));

                // Custom JSON Output Formatters Media Types
                if (setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault() is JsonOutputFormatter jsonOutputFormatter)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.nagarro.hateoas+json");
                }

                // Custom JSON Input Formatters Media Types
                if (setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault() is JsonInputFormatter jsonInputFormatter)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.nagarro.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.nagarro.authorwithdateofdeath.full+json");
                }
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = this.Configuration.GetConnectionString("libraryDBConnectionString");

            services.AddDbContextPool <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddCors(options =>
            {
                options.AddPolicy(this.AllowSpecificOrigins, builder => builder.WithOrigins("http://localhost:4200"));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // Configure Caching
            services.AddHttpCachingMvc();
            services.AddResponseCaching();

            // Configure Memory Cache
            services.AddMemoryCache();
            services.Configure <IpRateLimitOptions>(options =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>
                {
                    new RateLimitRule {
                        Endpoint = "*", Limit = 1000, Period = "1m"
                    },
                    new RateLimitRule {
                        Endpoint = "*", Limit = 200, Period = "10s"
                    }
                };
            });
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
Example #26
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => options.EnableEndpointRouting = false);

            //Microsoft.AspNetCore.Mvc.Formatters.Xml
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                //setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(setupAction));
            });

            services.AddMvc().AddNewtonsoftJson();
            services.AddMvc().AddMvcOptions(options =>
            {
                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter(options);
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                options.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = options.InputFormatters
                                         .OfType <NewtonsoftJsonOutputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = options.OutputFormatters
                                          .OfType <NewtonsoftJsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.hateoas+json");
                }
            });

            // Microsoft.AspNetCore.Mvc.NewtonsoftJson
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            // HttpPatch
            services.AddControllersWithViews().AddNewtonsoftJson();
            services.AddControllersWithViews(options =>
            {
                options.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
            });


            var config = new MapperConfiguration(cfg =>
            {
                /*cfg.CreateMap<Author, AuthorDto>()
                *  .ForMember(dest => dest.Name, opt => opt.MapFrom(src =>
                *    $"{src.FirstName} {src.LastName}"))
                *  .ForMember(dest => dest.Age, opt => opt.MapFrom(src =>
                *    src.DateOfBirth.GetCurrentAge()));*/

                cfg.CreateMap <Author, AuthorDto>()
                .ForMember(dest => dest.Name, opt => opt.MapFrom(src =>
                                                                 $"{src.FirstName} {src.LastName}"))
                .ForMember(dest => dest.Age, opt => opt.MapFrom(src =>
                                                                src.DateOfBirth.GetCurrentAge(src.DateOfDeath)));

                cfg.CreateMap <Book, BookDto>();

                cfg.CreateMap <AuthorForCreationDto, Author>();

                cfg.CreateMap <AuthorForCreationWithDateOfDeathDto, Author>();

                cfg.CreateMap <BookForCreationDto, Book>();

                cfg.CreateMap <BookForUpdateDto, Book>();

                cfg.CreateMap <Book, BookForUpdateDto>();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Startup.Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper, IUrlHelper>(implementationFactory =>
            {
                var actionContext =
                    implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // Nuget Marvin.Cache.Headers
            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                =>
            {
                expirationModelOptions.MaxAge = 600;
            },
                (validationModelOptions)
                =>
            {
                validationModelOptions.MustRevalidate = true;
            });

            // Nuget AspNetCoreRateLimit
            services.AddMemoryCache();

            /*services.Configure<IpRateLimitOptions>((options) =>
             * {
             *  options.GeneralRules = new System.Collections.Generic.List<RateLimitRule>()
             *  {
             *      new RateLimitRule()
             *      {
             *          Endpoint = "*",
             *          Limit = 1000,
             *          Period = "5m"
             *      }*//*,
             *      new RateLimitRule()
             *      {
             *          Endpoint = "*",
             *          Limit = 200,
             *          Period = "10s"
             *      }*//*
             *  };
             * });*/

            // needed to load configuration from appsettings.json
            services.AddOptions();

            // needed to store rate limit counters and ip rules
            services.AddMemoryCache();

            //load general configuration from appsettings.json
            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            //load ip rules from appsettings.json
            services.Configure <IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

            // inject counter and rules stores
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

            // Add framework services.
            services.AddMvc();

            // https://github.com/aspnet/Hosting/issues/793
            // the IHttpContextAccessor service is not registered by default.
            // the clientId/clientIp resolvers use it.
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            // configuration (resolvers, counter key builders)
            services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>();

            IMapper mapper = config.CreateMapper();

            services.AddSingleton(mapper);
        }
        public async Task ReadAsync_ThrowsWhenNotConfiguredWithKnownTypes()
        {
            // Arrange
            var KnownTypeName = "SomeDummyClass";
            var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";

            var input = string.Format(
                    "<DummyClass i:type=\"{0}\" xmlns:i=\"{1}\"><SampleInt>1</SampleInt>"
                    + "<SampleString>Some text</SampleString></DummyClass>",
                    KnownTypeName,
                    InstanceNamespace);
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));

            // Act & Assert
            await Assert.ThrowsAsync(typeof(SerializationException), async () => await formatter.ReadAsync(context));
        }
Example #28
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                // If this is true then if the client's Accept header's value is not supported by the Outputformatters here then,
                // HttpStatus Response Code 406 will be sent back to the client
                setupAction.ReturnHttpNotAcceptable = true;


                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                // **** We get hold of the FIRST JSON output formatter
                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();

                // and if it found then, we configure it to support custom media type shown below.
                // SO, as a result if the client sends an Http Request with an Accept: application/vnd.marvin.hateoas+json
                // the Output Formatter won't throw an error 406 Not Acceptable .....
                // Then in our controller's Action's parameter we could do
                // [FromHeader(Name="Accept") string x]
                // and then compare x to "application/vnd.marvin.hateoas+json" or to "application/json" and place different
                // stuff in the Http Response body and Http Response Header depending on the API documentation ....
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // ***************** This will add directives to the Cache-Control Http Response Header ******************************
            // There are many options and you will get intellisense when you do expirationModelOptions. or validationModelOptions.
            // ************************************ V IMP *******************************
            // This will ALSO add the eTag, Last-Modified & Expires Http headers in addition to the directives in the
            // Cache-Control Header

            services.AddHttpCacheHeaders((expirationModelOptions) => {
                expirationModelOptions.MaxAge = 600;
            },
                                         (validationModelOptions) => {
                validationModelOptions.AddMustRevalidate = true;
            });
            // *********************************************************************************************************************


            // *****************  This service allows us to do DATA caching in the server's memory *********************************
            //                    This is for DATA caching ... NOT NOT Http Response Caching ...
            //                    This is used by the IP Rate Limiting Middleware for storing API call counts in memory ....
            services.AddMemoryCache();



            // *****************  This is configuring the https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware
            //                    MIDDLEWARE which controls how frequently the web apis can be called
            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
            // ************************************************************************************************************************
        }
        public async Task PostingListofModels_WithBothRequiredAndDataMemberRequired_NoValidationErrors()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                        "<ArrayOfLaptop xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                        " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Laptop><Id>" +
                        "10</Id><SupportsVirtualization>true</SupportsVirtualization></Laptop></ArrayOfLaptop>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(List<Laptop>));

            // Act
            var model = await formatter.ReadAsync(context) as List<Laptop>;

            // Assert
            Assert.NotNull(model);
            Assert.Equal(1, model.Count);
            Assert.Equal(10, model[0].Id);
            Assert.Equal(true, model[0].SupportsVirtualization);
            Assert.Empty(context.ActionContext.ModelState);
        }
Example #30
0
        public void ConfigureServices(IServiceCollection services)
        {
            //Added the connection string
            // services.AddDbContext<LibraryContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:LibraryContext"]));
            // services.AddDbContext<LibraryContext>(options =>
            // options.UseSqlServer(Configuration.GetConnectionString("LibraryContext")));
            services.AddDbContext <LibraryContext>(options =>
                                                   options.UseSqlServer("Server=RAHUL-PC;Database=Author_Api;Trusted_Connection=True;MultipleActiveResultSets=true;"));
            // services.AddDbContext<LibraryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LibraryContext")));
            services.AddScoped <ILibraryRepository, LibraryRepository>();
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();
            // Auto Mapper Configurations
            var mappingConfig = new MapperConfiguration(mc =>
            {
                mc.AddProfile(new MappingProfile());
            });
            IMapper mapper = mappingConfig.CreateMapper();

            services.AddSingleton(mapper);

            // Set configuration to accept json or xml request type and return the response in the same type
            services.AddMvc(setUpAction =>
            {
                //Default is false, which means this support all request type and return only in default type(json)
                // Setting true we can force that to return the response in the specified type(XML)
                setUpAction.ReturnHttpNotAcceptable = true;
                // Setting output formatter
                setUpAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // Setting input formatter
                //setUpAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                // configure xml input formatter
                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.rahul.authorwithdateofdeath.full+xml");
                setUpAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                // configure custom input header
                var jsonInputFormatter = setUpAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.rahul.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.rahul.authorwithdateofdeath.full+json");
                }

                // configure custom output header
                var jsonOutputFormatter = setUpAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.rahul.hateoas+json");
                }
            })
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // Disable automatic model state validation before comes into the controller
            services.Configure <ApiBehaviorOptions>(options =>
            {
                options.SuppressModelStateInvalidFilter = true;
            });

            // Register the Swagger generator, defining 1 or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                // Add support for supporting multiple action with same path (api/CreateAuthor)
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                c.SwaggerDoc("v1", new Info {
                    Title       = "Author & Book service API",
                    Version     = "v1",
                    Description = "This is dummy API application for author and book service. This project is based on the REST architecture.",
                    Contact     = new Contact
                    {
                        Name  = "Rahul Sen",
                        Email = "*****@*****.**"
                    },
                    License = new License
                    {
                        Name = "Public - Mindfire",
                    }
                });
                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });

            // TODO:Update caching approach(https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-2.2)
            // Added http cache header middleware
            services.AddHttpCacheHeaders(
                (expirationModelOption) =>
            {
                // Added different directices
                expirationModelOption.MaxAge = 600;;
            },
                (validationModelOptions) =>
            {
                validationModelOptions.MustRevalidate = true;
            });

            // Add response caching related services
            services.AddResponseCaching();

            // register service for adding support to limit the request and for this it required a memory cache to count the request
            services.AddMemoryCache();
            // Limit for a particular ip address
            //services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        // full api endpoints
                        Endpoint = "*",
                        // limits 3 requests
                        Limit = 10,
                        // in 5 min time span can request resources for 10 times
                        Period = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 2,
                        Period   = "10s"
                    }
                };
            });

            // Register policy store and rate limit counter store
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>();
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
        }
        public async Task PostingModel_WithPropertySelfReferencingItself()
        {
            // Arrange
            var input = "<Employee xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Id>10</Id><Manager><Id>11</Id><Manager" +
                " i:nil=\"true\"/><Name>Mike</Name></Manager><Name>John</Name></Employee>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(Employee));
            var expectedModel = new Employee()
            {
                Id = 10,
                Name = "John",
                Manager = new Employee()
                {
                    Id = 11,
                    Name = "Mike"
                }
            };

            // Act
            var model = await formatter.ReadAsync(context) as Employee;

            // Assert
            Assert.NotNull(model);
            Assert.Equal(expectedModel.Id, model.Id);
            Assert.Equal(expectedModel.Name, model.Name);
            Assert.NotNull(model.Manager);
            Assert.Equal(expectedModel.Manager.Id, model.Manager.Id);
            Assert.Equal(expectedModel.Manager.Name, model.Manager.Name);
            Assert.Null(model.Manager.Manager);

            Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Employee).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
                });
        }
        public async Task PostingModel_WithDifferentValueTypeProperties_HasValidationErrors()
        {
            // Arrange
            var input = "<ValueTypePropertiesModel i:nil=\"true\" " +
                "xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\" " +
                "xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"/>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(ValueTypePropertiesModel));

            // Act
            var model = await formatter.ReadAsync(context);

            // Assert
            Assert.Null(model);

            Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Point).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName)
                });
            AssertModelStateErrorMessages(
                typeof(GpsCoordinate).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(
                        requiredErrorMessageFormat, 
                        nameof(GpsCoordinate.Latitude), 
                        typeof(GpsCoordinate).FullName),
                    string.Format(
                        requiredErrorMessageFormat, 
                        nameof(GpsCoordinate.Longitude), 
                        typeof(GpsCoordinate).FullName)
                });
            AssertModelStateErrorMessages(
                typeof(ValueTypePropertiesModel).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(
                        requiredErrorMessageFormat, 
                        nameof(ValueTypePropertiesModel.IntProperty), 
                        typeof(ValueTypePropertiesModel).FullName),
                    string.Format(
                        requiredErrorMessageFormat,
                        nameof(ValueTypePropertiesModel.DateTimeProperty),
                        typeof(ValueTypePropertiesModel).FullName),
                    string.Format(
                        requiredErrorMessageFormat,
                        nameof(ValueTypePropertiesModel.PointProperty),
                        typeof(ValueTypePropertiesModel).FullName),
                    string.Format(
                        requiredErrorMessageFormat,
                        nameof(ValueTypePropertiesModel.GpsCoordinateProperty),
                        typeof(ValueTypePropertiesModel).FullName)
                });
        }
Example #33
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());


                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.arubesu.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);


                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.arubesu.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.arubesu.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.arubesu.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            //register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext =
                    implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();
            services.AddHttpCacheHeaders(
                (ExpirationModelOptions) =>
                { ExpirationModelOptions.MaxAge = 600; },
                (validationModelOptions) =>
                { validationModelOptions.MustRevalidate = true; }
                );

            services.AddResponseCaching();

            // needed to load configuration from appsettings.json
            services.AddOptions();

            // needed to store rate limit counters and ip rules
            services.AddMemoryCache();

            //load general configuration from appsettings.json
            services.Configure <IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));

            // inject counter and rules stores
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

            // Register the Swagger generator
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info {
                    Title = "Library API", Version = "v1"
                });
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
            });
        }
Example #34
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });



            // *********************
            // Setup CORS
            // *********************
            var corsBuilder = new CorsPolicyBuilder();

            corsBuilder.AllowAnyHeader();
            corsBuilder.AllowAnyMethod();
            corsBuilder.AllowAnyOrigin(); // For anyone access.
            //corsBuilder.WithOrigins("http://localhost:54816"); // for a specific url. Don't add a forward slash on the end!
            corsBuilder.AllowCredentials();

            services.AddCors(options =>
            {
                options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
            });



            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            services.AddResponseCaching();

            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                =>
            {
                expirationModelOptions.MaxAge = 600;
            },
                (validationModelOptions)
                =>
            {
                validationModelOptions.AddMustRevalidate = true;
            });

            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();

            services.AddSwaggerGen(setupAction =>
            {
                setupAction.SwaggerDoc("libraryapi",
                                       new Swashbuckle.AspNetCore.Swagger.Info {
                    Title = "Library API Documentation"
                });
            });
        }
Example #35
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                // pokud je to false, tak nam vrati data v podporovanem formatu - JSON
                // pokud `nastavim ena true, tak nam to vyhodi 406 cybu pokud format nepodporujeme
                setupAction.ReturnHttpNotAcceptable = true;
                // nastavime ze pokud nekdo bude vyzadovat XML v headeru, tak mu ho posleme
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();
                // musime pridat vlastni MetaData type aby jsme ho mohli pouzivat
                // v Header Accept si normalne posleme jeho nazev a jen porovnavame se string/enum
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            }).AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();
            // pridame URLhealper k tomu abyu jsme mohli vytvaret previsous a next link
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                =>
            {
                expirationModelOptions.MaxAge = 600;
            },
                (validationModelOptions)
                =>
            {
                validationModelOptions.AddMustRevalidate = true;
            });

            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
        public async Task ReadAsync_AcceptsUTF16Characters()
        {
            // Arrange
            var expectedInt = 10;
            var expectedString = "TestString";

            var input = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
                                "<TestLevelOne><SampleInt>" + expectedInt + "</SampleInt>" +
                                "<sampleString>" + expectedString + "</sampleString></TestLevelOne>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);

            var modelState = new ModelStateDictionary();
            var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");

            var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
            
            // Act
            var model = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(model);
            Assert.IsType<TestLevelOne>(model);

            var levelOneModel = model as TestLevelOne;
            Assert.Equal(expectedInt, levelOneModel.SampleInt);
            Assert.Equal(expectedString, levelOneModel.sampleString);
        }
        public async Task ReadAsync_ReadsWhenMaxDepthIsModified()
        {
            // Arrange
            var expectedInt = 10;

            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<DummyClass><SampleInt>" + expectedInt + "</SampleInt></DummyClass>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            formatter.MaxDepth = 10;
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));


            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<DummyClass>(result.Model);
            Assert.Equal(expectedInt, model.SampleInt);
        }
        public void SetMaxDepth_ThrowsWhenMaxDepthIsBelowOne()
        {
            // Arrange
            var formatter = new XmlDataContractSerializerInputFormatter();

            // Act & Assert
            Assert.Throws(typeof(ArgumentException), () => formatter.MaxDepth = 0);
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>()
                                    .ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // services.AddScoped<IUrlHelper, UrlHelper>();
        }
        public async Task ReadAsync_FallsbackToUTF8_WhenCharSet_NotInContentType()
        {
            // Arrange
            var expectedException = TestPlatformHelper.IsMono ? typeof(SerializationException) :
                                                                typeof(XmlException);
            var expectedMessage = TestPlatformHelper.IsMono ?
                "Expected element 'TestLevelTwo' in namespace '', but found Element node 'DummyClass' in namespace ''" :
                "The expected encoding 'utf-8' does not match the actual encoding 'utf-16LE'.";
            var inpStart = Encoding.Unicode.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
                "<DummyClass><SampleInt>");
            byte[] inp = { 192, 193 };
            var inpEnd = Encoding.Unicode.GetBytes("</SampleInt></DummyClass>");

            var contentBytes = new byte[inpStart.Length + inp.Length + inpEnd.Length];
            Buffer.BlockCopy(inpStart, 0, contentBytes, 0, inpStart.Length);
            Buffer.BlockCopy(inp, 0, contentBytes, inpStart.Length, inp.Length);
            Buffer.BlockCopy(inpEnd, 0, contentBytes, inpStart.Length + inp.Length, inpEnd.Length);

            var formatter = new XmlDataContractSerializerInputFormatter();
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelTwo));

            // Act
            var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
            Assert.Equal(expectedMessage, ex.Message);
        }
Example #41
0
    // Set up application services
    public void ConfigureServices(IServiceCollection services)
    {
        // Add MVC services to the services container
        services.AddControllers()
        .AddXmlDataContractSerializerFormatters()
        .AddXmlSerializerFormatters();

        services.Configure <MvcOptions>(options =>
        {
            // Since both XmlSerializer and DataContractSerializer based formatters
            // have supported media types of 'application/xml' and 'text/xml',  it
            // would be difficult for a test to choose a particular formatter based on
            // request information (Ex: Accept header).
            // We'll configure the ones on MvcOptions to use a distinct set of content types.

            XmlSerializerInputFormatter xmlSerializerInputFormatter     = null;
            XmlSerializerOutputFormatter xmlSerializerOutputFormatter   = null;
            XmlDataContractSerializerInputFormatter dcsInputFormatter   = null;
            XmlDataContractSerializerOutputFormatter dcsOutputFormatter = null;

            for (var i = options.InputFormatters.Count - 1; i >= 0; i--)
            {
                switch (options.InputFormatters[i])
                {
                case XmlSerializerInputFormatter formatter:
                    xmlSerializerInputFormatter = formatter;
                    break;

                case XmlDataContractSerializerInputFormatter formatter:
                    dcsInputFormatter = formatter;
                    break;

                default:
                    options.InputFormatters.RemoveAt(i);
                    break;
                }
            }

            for (var i = options.OutputFormatters.Count - 1; i >= 0; i--)
            {
                switch (options.OutputFormatters[i])
                {
                case XmlSerializerOutputFormatter formatter:
                    xmlSerializerOutputFormatter = formatter;
                    break;

                case XmlDataContractSerializerOutputFormatter formatter:
                    dcsOutputFormatter = formatter;
                    break;

                default:
                    options.OutputFormatters.RemoveAt(i);
                    break;
                }
            }

            xmlSerializerInputFormatter.SupportedMediaTypes.Clear();
            xmlSerializerInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml-xmlser"));
            xmlSerializerInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml-xmlser"));
            xmlSerializerInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+xml"));

            xmlSerializerOutputFormatter.SupportedMediaTypes.Clear();
            xmlSerializerOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml-xmlser"));
            xmlSerializerOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml-xmlser"));
            xmlSerializerOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+xml"));

            dcsInputFormatter.SupportedMediaTypes.Clear();
            dcsInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml-dcs"));
            dcsInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml-dcs"));
            dcsInputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+xml"));

            dcsOutputFormatter.SupportedMediaTypes.Clear();
            dcsOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml-dcs"));
            dcsOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml-dcs"));
            dcsOutputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+xml"));

            options.InputFormatters.Add(dcsInputFormatter);
            options.InputFormatters.Add(xmlSerializerInputFormatter);
            options.OutputFormatters.Add(dcsOutputFormatter);
            options.OutputFormatters.Add(xmlSerializerOutputFormatter);

            xmlSerializerInputFormatter.WrapperProviderFactories.Add(new PersonWrapperProviderFactory());
            xmlSerializerOutputFormatter.WrapperProviderFactories.Add(new PersonWrapperProviderFactory());
            dcsInputFormatter.WrapperProviderFactories.Add(new PersonWrapperProviderFactory());
            dcsOutputFormatter.WrapperProviderFactories.Add(new PersonWrapperProviderFactory());
        });
    }
        public async Task ReadAsync_IgnoresBOMCharacters()
        {
            // Arrange
            var sampleString = "Test";
            var sampleStringBytes = Encoding.UTF8.GetBytes(sampleString);
            var inputStart = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine +
                "<TestLevelTwo><SampleString>" + sampleString);
            byte[] bom = { 0xef, 0xbb, 0xbf };
            var inputEnd = Encoding.UTF8.GetBytes("</SampleString></TestLevelTwo>");
            var expectedBytes = new byte[sampleString.Length + bom.Length];

            var contentBytes = new byte[inputStart.Length + bom.Length + inputEnd.Length];
            Buffer.BlockCopy(inputStart, 0, contentBytes, 0, inputStart.Length);
            Buffer.BlockCopy(bom, 0, contentBytes, inputStart.Length, bom.Length);
            Buffer.BlockCopy(inputEnd, 0, contentBytes, inputStart.Length + bom.Length, inputEnd.Length);

            var formatter = new XmlDataContractSerializerInputFormatter();
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelTwo));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<TestLevelTwo>(result.Model);
            Buffer.BlockCopy(sampleStringBytes, 0, expectedBytes, 0, sampleStringBytes.Length);
            Buffer.BlockCopy(bom, 0, expectedBytes, sampleStringBytes.Length, bom.Length);
            Assert.Equal(expectedBytes, Encoding.UTF8.GetBytes(model.SampleString));
        }
        public void HasProperSuppportedMediaTypes()
        {
            // Arrange & Act
            var formatter = new XmlDataContractSerializerInputFormatter();

            // Assert
            Assert.True(formatter.SupportedMediaTypes
                                 .Select(content => content.ToString())
                                 .Contains("application/xml"));
            Assert.True(formatter.SupportedMediaTypes
                                 .Select(content => content.ToString())
                                 .Contains("text/xml"));
        }
        public async Task ReadAsync_ThrowsWhenNotConfiguredWithRootName()
        {
            // Arrange
            var SubstituteRootName = "SomeOtherClass";
            var SubstituteRootNamespace = "http://tempuri.org";

            var input = string.Format(
                "<{0} xmlns=\"{1}\"><SampleInt xmlns=\"\">1</SampleInt></{0}>",
                SubstituteRootName,
                SubstituteRootNamespace);
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));

            // Act & Assert
            await Assert.ThrowsAsync(typeof(SerializationException), async () => await formatter.ReadAsync(context));
        }
        public async Task ReadAsync_ReadsComplexTypes()
        {
            // Arrange
            var expectedInt = 10;
            var expectedString = "TestString";
            var expectedLevelTwoString = "102";

            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<TestLevelTwo><SampleString>" + expectedLevelTwoString + "</SampleString>" +
                        "<TestOne><SampleInt>" + expectedInt + "</SampleInt>" +
                        "<sampleString>" + expectedString + "</sampleString></TestOne></TestLevelTwo>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelTwo));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<TestLevelTwo>(result.Model);

            Assert.Equal(expectedLevelTwoString, model.SampleString);
            Assert.Equal(expectedInt, model.TestOne.SampleInt);
            Assert.Equal(expectedString, model.TestOne.sampleString);
        }
        public async Task PostingModel_WithDeeperHierarchy_HasValidationErrors()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                        "<Store xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.AspNet.Mvc.Xml\"" +
                        " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" i:nil=\"true\" />";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(Store));

            // Act
            var model = await formatter.ReadAsync(context) as Store;

            // Assert
            Assert.Null(model);

            Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
            AssertModelStateErrorMessages(
                typeof(Address).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
                    string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName)
                });

            AssertModelStateErrorMessages(
                typeof(Employee).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
                });

            AssertModelStateErrorMessages(
                typeof(Product).FullName,
                context.ActionContext,
                expectedErrorMessages: new[]
                {
                    string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
                });
        }
        public async Task ReadAsync_ThrowsWhenReaderQuotasAreChanged()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<TestLevelTwo><SampleString>test</SampleString>" +
                        "<TestOne><SampleInt>10</SampleInt>" +
                        "<sampleString>test</sampleString></TestOne></TestLevelTwo>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            formatter.XmlDictionaryReaderQuotas.MaxStringContentLength = 2;
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelTwo));

            // Act & Assert
            await Assert.ThrowsAsync(typeof(SerializationException), async () => await formatter.ReadAsync(context));
        }
Example #48
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(
                setupAction =>
            {
                // ReturnHttpNotAcceptable forces consumer to specify a supported available data format
                // rather than defaulting to json when the consumer specifies an unsupported format such as xml.
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // Allow incoming requests (such as post) to use xml
                setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                // v2.1 - Support DoD posts using XML
                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                // v2 - Date of death support with versioning via media types
                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                // Add support for custom media type of 'application/vnd.marvin.hateoas+json' using json
                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddJsonOptions(
                options =>
            {
                // Retain property name casing on serialization.
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            // register IUrlHelper to support returning pagination metadata from a controller
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();            // Provides IUrlHelper with access to actions
            //services.AddScoped<IUrlHelper, UrlHelper>(); // Generates URIs for an action
            services.AddScoped <IUrlHelper, UrlHelper>(
                implementationFactory =>
            {
                return(new UrlHelper(actionContext: implementationFactory.GetService <IActionContextAccessor>().ActionContext));
            });


            // Register custom IPropertyMappingService to support sorting
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            // Register custom service to support data shaping
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            // Add some support for caching with HTTP cache headers
            //services.AddHttpCacheHeaders();
            // Can use this to configure the cache headers in the response for both the expiration and validation models
            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                =>
                { expirationModelOptions.MaxAge = 600; },
                (validationModelOptions)
                =>
                { validationModelOptions.MustRevalidate = true; });

            // Use MS .Net Core package for response caching. Seems to be the only option available.
            // Does not generate response headers (like marvin does) but it does handle them.
            // Before v2 there are some really nasty bugs so avoid v1!
            services.AddResponseCaching();

            // Support for throttling...
            // Can throttle by IP and / or by client.
            // Can throttle by calls to specific controllers or methods
            // Can throttle by (for example); requests per day, requests per hour, and requests per controller.
            // Request headers for this are; X-Rate-Limit-Limit, X-Rate-Limit-Remaining, and X-Rate-Limit-Reset.
            // Disallowed requests will return a 429 response with an optional Retry-After header and a body explaining the condition.

            services.AddMemoryCache();             // Used to store throttling counters and rules

            // AspNetCoreRateLimit package contains two pieces of middleware for throttling by IP and by client.
            // Example for throttling by IP...
            // NB - Could also read this from the config file (not sure if a specific one should be used or just the appsettings.json)

            services.Configure <IpRateLimitOptions>(
                options =>
            {
                options.GeneralRules = new List <RateLimitRule>
                {
                    new RateLimitRule                             // 10 requests every 5 minutes
                    {
                        Endpoint = "*",
                        //Limit = 10,
                        Limit  = 1000,
                        Period = "5m"
                    },
                    new RateLimitRule                             // 2 requests every 10 seconds
                    {
                        Endpoint = "*",
                        //Limit = 2,
                        Limit  = 200,
                        Period = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
        public async Task ReadAsync_VerifyStreamIsOpenAfterRead()
        {
            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<DummyClass><SampleInt>10</SampleInt></DummyClass>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            Assert.NotNull(result.Model);
            Assert.True(context.HttpContext.Request.Body.CanRead);
        }
        public async Task ReadAsync_ReadsSimpleTypes()
        {
            // Arrange
            var expectedInt = 10;
            var expectedString = "TestString";

            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                                "<TestLevelOne><SampleInt>" + expectedInt + "</SampleInt>" +
                                "<sampleString>" + expectedString + "</sampleString></TestLevelOne>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelOne));

            // Act
            var model = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(model);
            Assert.IsType<TestLevelOne>(model);

            var levelOneModel = model as TestLevelOne;
            Assert.Equal(expectedInt, levelOneModel.SampleInt);
            Assert.Equal(expectedString, levelOneModel.sampleString);
        }
        public async Task ReadAsync_UsesContentTypeCharSet_ToReadStream()
        {
            // Arrange
            var expectedException = TestPlatformHelper.IsMono ? typeof(SerializationException) :
                                                                typeof(XmlException);
            var expectedMessage = TestPlatformHelper.IsMono ?
                "Expected element 'TestLevelTwo' in namespace '', but found Element node 'DummyClass' in namespace ''" :
                "The expected encoding 'utf-16LE' does not match the actual encoding 'utf-8'.";
            var inputBytes = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<DummyClass><SampleInt>1000</SampleInt></DummyClass>");

            var formatter = new XmlDataContractSerializerInputFormatter();

            var modelState = new ModelStateDictionary();
            var httpContext = GetHttpContext(inputBytes, contentType: "application/xml; charset=utf-16");

            var context = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                modelType: typeof(TestLevelOne));

            // Act
            var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
            Assert.Equal(expectedMessage, ex.Message);
        }
        public async Task ReadAsync_ThrowsOnExceededMaxDepth()
        {
            if (TestPlatformHelper.IsMono)
            {
                // ReaderQuotas are not honored on Mono
                return;
            }

            // Arrange
            var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<TestLevelTwo><SampleString>test</SampleString>" +
                        "<TestOne><SampleInt>10</SampleInt>" +
                        "<sampleString>test</sampleString></TestOne></TestLevelTwo>";
            var formatter = new XmlDataContractSerializerInputFormatter();
            formatter.MaxDepth = 1;
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(TestLevelTwo));

            // Act & Assert
            await Assert.ThrowsAsync(typeof(SerializationException), async () => await formatter.ReadAsync(context));
        }
        public async Task ReadAsync_AcceptsUTF16Characters()
        {
            // Arrange
            var expectedInt = 10;
            var expectedString = "TestString";

            var input = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
                                "<TestLevelOne><SampleInt>" + expectedInt + "</SampleInt>" +
                                "<sampleString>" + expectedString + "</sampleString></TestLevelOne>";

            var formatter = new XmlDataContractSerializerInputFormatter();
            var contentBytes = Encoding.Unicode.GetBytes(input);

            var modelState = new ModelStateDictionary();
            var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");

            var context = new InputFormatterContext(
                httpContext,
                modelName: string.Empty,
                modelState: modelState,
                modelType: typeof(TestLevelOne));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<TestLevelOne>(result.Model);

            Assert.Equal(expectedInt, model.SampleInt);
            Assert.Equal(expectedString, model.sampleString);
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(new MvcOptions()));

                var xmlDataContractSerializerInputFormatter =
                    new XmlDataContractSerializerInputFormatter();

                xmlDataContractSerializerInputFormatter.SupportedMediaTypes
                .Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters
                                         .OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes
                    .Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters
                                          .OfType <JsonOutputFormatter>().FirstOrDefault();

                jsonOutputFormatter?.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
            }).AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version        = "v1",
                    Title          = "Library RESTful API",
                    Description    = "Pluralsight Course: Building a RESTful API with ASP.NET Core",
                    TermsOfService = "None",
                    Contact        = new Contact()
                    {
                        Name = "Justin Grimes", Email = "*****@*****.**", Url = "*****@*****.**"
                    }
                });
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = _configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            // register action context accessor
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            // register url helper
            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext =
                    implementationFactory.GetService <IActionContextAccessor>().ActionContext;

                return(new UrlHelper(actionContext));
            });

            // register property mapping service
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            // register type helper service
            services.AddTransient <ITypeHelperService, TypeHelperService>();
        }
        public async Task ReadAsync_ReadsWhenConfiguredWithRootName()
        {
            // Arrange
            var expectedInt = 10;
            var SubstituteRootName = "SomeOtherClass";
            var SubstituteRootNamespace = "http://tempuri.org";

            var input = string.Format(
                "<{0} xmlns=\"{1}\"><SampleInt xmlns=\"\">{2}</SampleInt></{0}>",
                SubstituteRootName,
                SubstituteRootNamespace,
                expectedInt);

            var dictionary = new XmlDictionary();
            var settings = new DataContractSerializerSettings
            {
                RootName = dictionary.Add(SubstituteRootName),
                RootNamespace = dictionary.Add(SubstituteRootNamespace)
            };
            var formatter = new XmlDataContractSerializerInputFormatter
            {
                SerializerSettings = settings
            };
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<DummyClass>(result.Model);
            Assert.Equal(expectedInt, model.SampleInt);
        }
Example #56
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(opt =>
            {
                opt.ReturnHttpNotAcceptable = true;
                opt.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                // opt.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(opt));

                var xmlDataContractSerializerInputFormatter = new XmlDataContractSerializerInputFormatter(opt);

                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                xmlDataContractSerializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+xml");

                opt.InputFormatters.Add(xmlDataContractSerializerInputFormatter);

                var jsonInputFormatter = opt.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");

                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                }



                var jsonOutputFormatter = opt.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath+json");
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            .AddXmlDataContractSerializerFormatters()
            .AddJsonOptions(option =>
            {
                option.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            services.AddCors(opt =>
            {
                opt.AddPolicy("AllowOrigin", options =>
                {
                    options.AllowAnyOrigin();
                    options.AllowAnyHeader();
                    options.AllowAnyMethod();
                });
            });


            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            //generating prev and next routes
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            //Caching & concurrency

            services.AddHttpCacheHeaders(expirationOptions =>
            {
                expirationOptions.MaxAge = 600;
            }, validationOptions =>
            {
                validationOptions.MustRevalidate = true;
            });

            //Caching & concurrency
            services.AddResponseCaching();



            // Rate Limiting
            services.AddMemoryCache();
            services.Configure <IpRateLimitOptions>(opt =>
            {
                opt.GeneralRules = new List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();

            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>();
        }
        public async Task ReadAsync_ReadsWhenConfiguredWithKnownTypes()
        {
            // Arrange
            var expectedInt = 10;
            var expectedString = "TestString";
            var KnownTypeName = "SomeDummyClass";
            var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";

            var input = string.Format(
                    "<DummyClass i:type=\"{0}\" xmlns:i=\"{1}\"><SampleInt>{2}</SampleInt>"
                    + "<SampleString>{3}</SampleString></DummyClass>",
                    KnownTypeName,
                    InstanceNamespace,
                    expectedInt,
                    expectedString);
            var settings = new DataContractSerializerSettings
            {
                KnownTypes = new[] { typeof(SomeDummyClass) }
            };
            var formatter = new XmlDataContractSerializerInputFormatter
            {
                SerializerSettings = settings
            };
            var contentBytes = Encoding.UTF8.GetBytes(input);
            var context = GetInputFormatterContext(contentBytes, typeof(DummyClass));

            // Act
            var result = await formatter.ReadAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.HasError);
            var model = Assert.IsType<SomeDummyClass>(result.Model);
            Assert.Equal(expectedInt, model.SampleInt);
            Assert.Equal(expectedString, model.SampleString);
        }
Example #58
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(
                setup =>
            {
                setup.ReturnHttpNotAcceptable = true;
                setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

                var xmlInputFormatter = new XmlDataContractSerializerInputFormatter(new MvcOptions {
                });
                xmlInputFormatter.SupportedMediaTypes.Add(VendorMediaType.NewAuthorDeadXml);

                setup.InputFormatters.Add(xmlInputFormatter);

                var jsonOutputFormatter = setup.OutputFormatters.OfType <NewtonsoftJsonOutputFormatter>().FirstOrDefault();
                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add(VendorMediaType.HateoasLinks);
                }


                var jsonInputFormatter = setup.InputFormatters.OfType <NewtonsoftJsonInputFormatter>().FirstOrDefault();
                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add(VendorMediaType.NewAuthor);
                    jsonInputFormatter.SupportedMediaTypes.Add(VendorMediaType.NewAuthorDead);
                }
                //setup.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
            }
                ).AddNewtonsoftJson(options =>
                                    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()
                                    )
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

            services.AddControllersWithViews(options =>
            {
                options.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
            });
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));
            services.AddScoped <ILibraryRepository, LibraryRepository>();
            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper, UrlHelper>(imp =>
            {
                var actionContext = imp.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            }
                                                       );

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            services.AddHttpCacheHeaders(
                options =>
            {
                options.MaxAge = 600;
            },
                validationOptions =>
            {
                validationOptions.AddMustRevalidate = true;
            }
                );

            services.AddResponseCaching();

            services.AddMemoryCache();

            services.AddSingleton <IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>();

            services.AddMemoryCache();
            services.AddSingleton <IClientPolicyStore, MemoryCacheClientPolicyStore>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                                   //PeriodTimespan = new TimeSpan(0,5,0)
                    },
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                                   //PeriodTimespan = new TimeSpan(0,0,10)
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                //setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());

                var xmlDataContractSarializerInputFormatter = new XmlDataContractSerializerInputFormatter();
                xmlDataContractSarializerInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");

                setupAction.InputFormatters.Add(xmlDataContractSarializerInputFormatter);

                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+json");
                }

                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.alienonwork.hateoas+json");
                }
            })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();
            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            services.AddTransient <IPropertyMappingService, PropertyMappingService>();

            services.AddTransient <ITypeHelperService, TypeHelperService>();

            services.AddHttpCacheHeaders(
                (expirationModelOptions)
                => expirationModelOptions.MaxAge = 600,
                (validationModelOptions)
                =>
            {
                validationModelOptions.AddMustRevalidate = true;
            });

            services.AddResponseCaching();

            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>((options) =>
            {
                options.GeneralRules = new System.Collections.Generic.List <RateLimitRule>()
                {
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 1000,
                        Period   = "5m"
                    },
                    new RateLimitRule()
                    {
                        Endpoint = "*",
                        Limit    = 200,
                        Period   = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }
Example #60
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;

                // default outputformatter: the first one in this list
                // it will be used if no accept-header was specified
                setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                //setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(new MvcOptions()));

                var xmlDataContractSerializer = new XmlDataContractSerializerInputFormatter(new MvcOptions());
                xmlDataContractSerializer.SupportedMediaTypes.Add("application/vnd.marvin.authorwithdateofdeath.full+xml");
                setupAction.InputFormatters.Add(xmlDataContractSerializer);

                var jsonInputFormatter = setupAction.InputFormatters.OfType <JsonInputFormatter>().FirstOrDefault();

                if (jsonInputFormatter != null)
                {
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.author.full+json");
                    jsonInputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.authorwithtimeofdeath.full+json");
                }


                var jsonOutputFormatter = setupAction.OutputFormatters.OfType <JsonOutputFormatter>().FirstOrDefault();

                if (jsonOutputFormatter != null)
                {
                    jsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            })
            // the default contract resolver serializes the data "as-is", and now we use ExpandoObject for data repr.
            // before the serialization, whose dictionary'keys are not camel case.
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            // register the DbContext on the container, getting the connection string from
            // appSettings (note: use this during development; in a production environment,
            // it's better to store the connection string in an environment variable)
            var connectionString = Configuration["connectionStrings:libraryDBConnectionString"];

            services.AddDbContext <LibraryContext>(o => o.UseSqlServer(connectionString));

            // register the repository
            services.AddScoped <ILibraryRepository, LibraryRepository>();

            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();

            services.AddScoped <IUrlHelper, UrlHelper>(implementationFactory =>
            {
                var actionContext = implementationFactory.GetService <IActionContextAccessor>().ActionContext;
                return(new UrlHelper(actionContext));
            });

            // lightweight, stateless ->transient
            services.AddTransient <IPropertyMappingService, PropertyMappingService>();
            services.AddTransient <ITypeHelperService, TypeHelperService>();

            services.AddHttpCacheHeaders(
                (ExpirationModelOptions expirationModelOptions)
                =>
            {
                expirationModelOptions.MaxAge = 600;
            },
                (ValidationModelOptions validationModelOptions)
                =>
            {
                validationModelOptions.MustRevalidate = true;
            });

            services.AddResponseCaching();

            services.AddMemoryCache();

            services.Configure <IpRateLimitOptions>(options =>
            {
                options.GeneralRules = new List <RateLimitRule>
                {
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        //Limit = 10,
                        Limit  = 1000,
                        Period = "5m"
                    },
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        //Limit = 2,
                        Limit  = 200,
                        Period = "10s"
                    }
                };
            });

            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
        }