using System.IO; using System.Linq; using System.Reflection; using System.Text; using AutoMapper; using FirebaseAdmin; using FluentValidation.AspNetCore; using Google.Apis.Auth.OAuth2; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Versioning; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.IdentityModel.Tokens; using OnlineAssessment.Common; using OnlineAssessment.Data; using OnlineAssessment.Data.EFCore; using Serilog; using Swashbuckle.AspNetCore.SwaggerGen; namespace OnlineAssessment { public class Startup { public IConfiguration Configuration { get; } //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // Startup //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx public Startup(IConfiguration configuration, IWebHostEnvironment env) { //Getting Response Messages From Config File (appresponsemessages.json) dynamic builder; if (env.EnvironmentName.Equals("Development")) { builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true) .AddJsonFile("appresponsemessages.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); } else { builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile("appresponsemessages.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); } configuration = builder.Build(); Configuration = configuration; } //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider) { app.UseStaticFiles(); app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), "Content")), RequestPath = "/Content" }); //RequestLoggingMiddleware string shouldLogRequest = Configuration["Logging:ShouldLogEveryRequest"]; if (shouldLogRequest.ToLower().Equals("yes")) { app.UseSerilogRequestLogging(); } // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui app.UseSwaggerUI( options => { //options.InjectJavascript("/Content/custom.js"); options.InjectStylesheet("/Content/custom.css"); // build a swagger endpoint for each discovered API version foreach (var description in provider.ApiVersionDescriptions) { options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); } }); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware(typeof(ErrorHandlingMiddleware)); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // This method gets called by the runtime. Use this method to add services to the container. //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx public void ConfigureServices(IServiceCollection services) { //Firebase FirebaseApp.Create(new AppOptions { Credential = GoogleCredential.FromFile(@"Firebase//practice-kea-7cb5b-firebase-adminsdk-e4h19-6e05200a3f.json") }); //------------------------------------------------------------------------------------------- // services.AddAutoMapper(typeof(AutoMapping)); //------------------------------------------------------------------------------------------- // services.AddDbConnections(Configuration); //------------------------------------------------------------------------------------------- //Repository Pattern classes add services.AddScoped(); services.AddScoped(); //------------------------------------------------------------------------------------------- // services.AddCors(o => o.AddPolicy("OdiwarePolicy", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() //.AllowCredentials() .Build(); })); //------------------------------------------------------------------------------------------- // //Firebase services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = "https://securetoken.google.com/practice-kea-7cb5b"; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "https://securetoken.google.com/practice-kea-7cb5b", ValidateAudience = true, ValidAudience = "practice-kea-7cb5b", ValidateLifetime = true, ValidateIssuerSigningKey = true }; }); /* services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, //ValidIssuer = Configuration["Jwt:Issuer"], //ValidAudience = Configuration["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; }); */ services.AddControllers() .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining()) .AddNewtonsoftJson(option => option.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); //------------------------------------------------------------------------------------------- // services.AddApiVersioning(config => { // Specify the default API Version as 1.0 config.DefaultApiVersion = new ApiVersion(1, 0); // If the client hasn't specified the API version in the request, use the default API version number config.AssumeDefaultVersionWhenUnspecified = true; // Advertise the API versions supported for the particular endpoint // Reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions" config.ReportApiVersions = true; // Supporting multiple versioning scheme //config.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("X-version"), new QueryStringApiVersionReader("api-version")); config.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("X-version")); }); //------------------------------------------------------------------------------------------- // services.AddVersionedApiExplorer( options => { // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service // note: the specified format code will format the version as "'v'major[.minor][-status]" options.GroupNameFormat = "'v'VVV"; // note: this option is only necessary when versioning by url segment. the SubstitutionFormat // can also be used to control the format of the API version in route templates options.SubstituteApiVersionInUrl = true; }); //------------------------------------------------------------------------------------------- // services.AddTransient, SwaggerConfigureOptions>(); services.AddSwaggerGen( options => { // add a custom operation filter which sets default values options.OperationFilter(); // integrate xml comments options.IncludeXmlComments(XmlCommentsFilePath); }); //------------------------------------------------------------------------------------------- // services.AddSingleton(Configuration.GetSection("ResponseMessage").Get()); services.Configure((setting) => { Configuration.GetSection("ResponseMessage").Bind(setting); }); services.Configure(a => a.InvalidModelStateResponseFactory = actionContext => { return new BadRequestObjectResult(new ReturnResponse(string.Empty, new ReturnStatus( "-1", actionContext.ModelState.Values.SelectMany(x => x.Errors) .Select(x => x.ErrorMessage) ) )); }); //------------------------------------------------------------------------------------------- } static string XmlCommentsFilePath { get { var basePath = PlatformServices.Default.Application.ApplicationBasePath; var fileName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name + ".xml"; return Path.Combine(basePath, fileName); } } } }