// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureContainer(ServiceRegistry services) { services.AddCorrelationId(); services.AddHttpContextAccessor(); services.AddMvc(); services.AddVersionedApiExplorer(options => options.GroupNameFormat = "'v'VVV"); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.DefaultApiVersion = new ApiVersion(1, 0); o.AssumeDefaultVersionWhenUnspecified = true; }); services.AddOptions(); services.AddHttpClient(); services.AddSwagger(Configuration); services.AddDependencyInjection(Configuration); services.AddControllers(); services.AddHealthChecks(); services.AddSwaggerGen(c => { // This coupled with the properties in the csproj allow the swagger page to show additional comments for methods var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureContainer(ServiceRegistry services) { services.AddDefaultCorrelationId(); services.AddHttpContextAccessor(); services.AddMvc(); services.AddVersionedApiExplorer(options => options.GroupNameFormat = "'v'VVV"); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.DefaultApiVersion = new ApiVersion(1, 0); o.AssumeDefaultVersionWhenUnspecified = true; }); services.AddOptions(); services.AddHttpClient(string.Empty) .AddCorrelationIdForwarding(); services.AddSwagger(); services.AddHealthChecks().AddCheck <ReadinessCheck>("PROJECT_NAME readiness", tags: new[] { "readiness" }); services.AddCustomizedLogging(); services.AddDependencyInjection(Configuration); services.AddHealthChecks(); services.AddControllers() .AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureContainer(ServiceRegistry services) { services.AddHttpClient("httpClientFactory"); services.Scan(s => { s.TheCallingAssembly(); s.WithDefaultConventions(); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
public void ConfigureContainer(ServiceRegistry services) { services.AddMvc(); services.AddLogging(); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()); services.For <IMessageMaker>().Use(new MessageMaker("Hey there.")); services.AddAuthentication() .AddIdentityServerAuthentication(options => { options.Authority = "auth"; options.RequireHttpsMetadata = true; }); services.AddHttpClient(); }
static async Task Main(string[] args) { var assembly = Assembly.GetExecutingAssembly(); var configuration = ConsoleConfigurationBuilder.BuildConfiguration(args, assembly); var serviceRegistry = new ServiceRegistry(); serviceRegistry.Scan(s => { // Look for any registry in a DLL we built. s.AssembliesAndExecutablesFromApplicationBaseDirectory(f => f?.FullName?.StartsWith("Fulgoribus.", StringComparison.OrdinalIgnoreCase) ?? false); s.LookForRegistries(); }); serviceRegistry.AddHttpClient(); // Need to use a lamba to resolve the SqlConnection because trying to bind by type was going off into setter injection land. serviceRegistry.For <IDbConnection>().Use(_ => new SqlConnection(configuration.GetConnectionString("DefaultConnection"))).Scoped(); using var container = new Container(serviceRegistry); var bookRepo = container.GetInstance <IBookRepository>(); var regexVolume = new Regex("[0-9]+[0-9.]*", RegexOptions.Compiled); var regexCover = new Regex(@"""https:\/\/c\.bookwalker\.jp\/([0-9]+)\/.*\.jpg""", RegexOptions.Compiled); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var httpClientFactory = container.GetInstance <IHttpClientFactory>(); using (var sqlConnection = new SqlConnection(configuration.GetConnectionString("DefaultConnection"))) using (var reader = new StreamReader(configuration["BookwalkerImport:ImportPath"], Encoding.GetEncoding(932))) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Configuration.RegisterClassMap <BookwalkerBookMap>(); await foreach (var record in csv.EnumerateRecordsAsync(new BookwalkerBook())) { if (record.Url?.StartsWith("https://global.bookwalker.jp") ?? false) { if (record.Category == Categories.ArtBook || record.Category == Categories.BookshelfSkin || record.Category == Categories.LiteratureAndNovels || record.Category == Categories.Manga || record.Category == Categories.NonFiction) { // Do nothing. } else if (record.Category == Categories.LightNovel) { var bookId = record.Url.Replace("https://global.bookwalker.jp/", string.Empty).Replace("/", string.Empty); var book = await bookRepo.GetBookByRetailerAsync("BW", bookId); if (book == null) { book = new Book { Title = record.Title, ReleaseDate = record.ReleaseDate, Label = record.Label }; await bookRepo.SaveBookAsync(book); var seriesTitle = record.Series.GetValueOrNull(); if (seriesTitle != null) { var series = await bookRepo.GetSeriesAsync(seriesTitle); if (series == null) { series = new Series { Title = seriesTitle }; await bookRepo.SaveSeriesAsync(series); } // Try to get the sort order as the first number in the title (to handle Kokoro Connect Volumes 9/10) that is not // part of the series (to handle 86). decimal?sortOrder = null; var titleForParsing = book.Title.Replace(seriesTitle, string.Empty); var volumeCandidates = regexVolume.Matches(titleForParsing); var books = await bookRepo.GetSeriesBooksAsync(series.SeriesId !.Value); if (volumeCandidates.Any()) { // Take the first one. sortOrder = Convert.ToDecimal(volumeCandidates.First().Value); // Make sure this doesn't collide with an existing volume. (e.g. Ascendance of a Bookworm) if (books.Any(b => b.SortOrder == sortOrder)) { sortOrder = null; } } if (!sortOrder.HasValue) { Console.WriteLine($"Unknown series order for series {seriesTitle}, book {book.Title}. Picking next available integer."); if (books.Any()) { var lastSortOrder = books.Last().SortOrder !.Value; sortOrder = Math.Ceiling(lastSortOrder); if (sortOrder == lastSortOrder) { sortOrder += 1; } } else { sortOrder = 1; } } var seriesBook = new SeriesBook { Series = series, Book = book, SortOrder = sortOrder, Volume = sortOrder.ToString() }; await bookRepo.SaveSeriesBookAsync(seriesBook); } var bookRetailer = new BookRetailer { BookId = book.BookId, RetailerId = "BW", RetailerKey = bookId }; await bookRepo.SaveBookRetailerAsync(bookRetailer); } if (book.BookId.HasValue) { var cover = await bookRepo.GetBookCoverAsync(book.BookId.Value); if (cover == null) { cover = new BookCover { BookId = book.BookId.Value }; try { var client = httpClientFactory.CreateClient(); var body = await client.GetStringAsync(record.Url); var matches = regexCover.Matches(body); if (matches.Any() && int.TryParse(new string(matches.First().Groups[1].Value.Reverse().ToArray()), out var id)) { var imageUrl = "http://c.bookwalker.jp/coverImage_" + (id - 1) + ".jpg"; var result = await client.GetAsync(imageUrl); if (result.StatusCode == HttpStatusCode.Forbidden) { // Try using the URL as-is. Not as good as the full-fat cover but it will do. var quotedUrl = matches.First().Value; var url = quotedUrl[1..^ 1];