Initial commit

This commit is contained in:
Fergal Moran
2019-02-06 00:18:07 +00:00
commit 0e0a5e3417
17 changed files with 919 additions and 0 deletions

280
.gitignore vendored Normal file
View File

@@ -0,0 +1,280 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.vcxproj.filters
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/
.vscode/
.idea/
appsettings.Development.json
appsettings.Production.json

View File

@@ -0,0 +1,26 @@
using System;
using System.Threading.Tasks;
using retns.api.Data;
using retns.api.Data.Models;
using retns.api.Services.Extensions;
using Microsoft.AspNetCore.Mvc;
namespace retns.homework.api.Controllers {
[Route("api/[controller]")]
[ApiController]
public class CalendarController : ControllerBase {
private readonly HomeworkService _service;
public CalendarController(HomeworkService service) {
this._service = service;
}
[HttpGet]
public async Task<ActionResult<HomeworkWeek>> Get() {
var key = DateTime.Now.GetThisMonday()
.ToString("ddMMyy");
var week = await _service.Get(key);
return Ok(week);
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Threading.Tasks;
using retns.api.Services;
using retns.api.Services.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace retns.homework.api.Controllers {
[Route("api/[controller]")]
[ApiController]
public class DocUploadController : ControllerBase {
private readonly ILogger<DocUploadController> _logger;
private readonly HomeworkFileParser _parser;
public DocUploadController(ILogger<DocUploadController> logger, HomeworkFileParser parser) {
this._logger = logger;
this._parser = parser;
}
// POST api/values
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public async Task<ActionResult> Post([FromForm] string url, [FromForm] string filename) {
_logger.LogDebug($"New event received\n\tFile url: {url}\n\tFile name: {filename}");
if (!filename.EndsWith("doc") && !filename.EndsWith("docx")) {
filename = $"{filename.TrimEnd('.')}.doc";
}
if (!string.IsNullOrEmpty(url)) {
if (await _parser.ProcessFromUrl(url, filename)) {
return Ok();
}
}
return BadRequest();
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using retns.api.Data.Settings;
using retns.api.Services.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using HtmlAgilityPack;
using System.Linq;
namespace retns.homework.api.Controllers {
[Route("api/[controller]")]
[ApiController]
public class GetHomeworkController : ControllerBase {
private readonly StorageSettings _storageSettings;
private readonly HttpClient _httpClient;
public GetHomeworkController(IOptions<StorageSettings> storageSettings,
IHttpClientFactory httpClientFactory) {
this._storageSettings = storageSettings.Value;
this._httpClient = httpClientFactory.CreateClient("AzureClient");
}
[HttpGet]
public async Task<IActionResult> GetCurrentWeek() {
var fileName =
DateTime.Now.GetThisMonday(DayOfWeek.Monday)
.ToString("ddMMyy") +
".html";
using (var wc = new System.Net.WebClient()) {
var result = await _httpClient.GetAsync($"html/{fileName}");
if (result.IsSuccessStatusCode) {
Stream stream = await result.Content.ReadAsStreamAsync();
HtmlDocument doc = new HtmlDocument();
doc.Load(stream);
var html = doc.DocumentNode.SelectSingleNode("//body");
html.Descendants("div")
.Where(n => n.Attributes["title"] != null && n.Attributes["title"].Value == "header")
.FirstOrDefault().RemoveAll();
foreach (var node in html.SelectNodes("//table")) {
node.Attributes.Append("class", "table table-striped");
}
return Ok(html.InnerHtml);
}
}
return NotFound();
}
}
}

42
Data/HomeworkService.cs Normal file
View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using retns.api.Data.Models;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using System.Threading.Tasks;
namespace retns.api.Data {
public class HomeworkService {
private readonly IMongoCollection<HomeworkWeek> _homeworkWeeks;
public HomeworkService(IConfiguration config) {
var client = new MongoClient(config.GetConnectionString("HomeworkDb"));
var database = client.GetDatabase("retns");
_homeworkWeeks = database.GetCollection<HomeworkWeek>("Homework");
}
public async Task<List<HomeworkWeek>> Get() {
return (await _homeworkWeeks.FindAsync(homework => true)).ToList();
}
public async Task<HomeworkWeek> Get(string id) {
return (await _homeworkWeeks.FindAsync<HomeworkWeek>(homework => homework.Id == id)).FirstOrDefault();
}
public async Task<HomeworkWeek> Create(HomeworkWeek homework) {
await _homeworkWeeks.InsertOneAsync(homework);
return homework;
}
public async Task Update(string id, HomeworkWeek homeworkIn) {
await _homeworkWeeks.ReplaceOneAsync(homework => homework.Id == id, homeworkIn);
}
public async Task Remove(HomeworkWeek homeworkIn) {
await _homeworkWeeks.DeleteOneAsync(homework => homework.Id == homeworkIn.Id);
}
public async Task Remove(string id) {
await _homeworkWeeks.DeleteOneAsync(homework => homework.Id == id);
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Options;
namespace retns.api.Data.Models {
public class HomeworkWeek {
public HomeworkWeek(string id) {
this.Id = id;
this.Days = new Dictionary<DayOfWeek, Dictionary<string, string>>();
}
[BsonId]
[BsonRepresentation(BsonType.String)]
public string Id { get; set; }
[BsonElement("WeekCommencing")]
public DateTime WeekCommencing { get; set; }
[BsonElement("WeekCNotesommencing")]
public string Notes { get; set; }
[BsonElement("Subjects")]
public List<string> Subjects;
[BsonElement("Days")]
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
public Dictionary<DayOfWeek, Dictionary<string, string>> Days { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace retns.api.Data.Settings {
public class StorageSettings {
public string ConnectionString { get; set; }
public string CdnUrl { get; set; }
}
}

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
FROM microsoft/dotnet:sdk AS build-env
WORKDIR /app
EXPOSE 5000
# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
# spin up the runtime
FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "retns.homework.api.dll"]

25
Program.cs Normal file
View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace retns.homework.api {
public class Program {
public static void Main(string[] args) {
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel(options => {
options.Listen(IPAddress.Any, 5000);
});
}
}

83
Services/AzureHelper.cs Normal file
View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using retns.api.Data.Settings;
using Microsoft.Extensions.Options;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
namespace retns.api.Services {
public class AzureHelper {
private readonly CloudBlobClient _blobClient;
public AzureHelper(IOptions<StorageSettings> settings) {
var storageAccount = CloudStorageAccount.Parse(settings.Value.ConnectionString);
_blobClient = storageAccount.CreateCloudBlobClient();
}
public async Task<bool> FileExists(string containerName, string fileName) {
var result = await _blobClient.GetContainerReference(containerName)
.GetBlockBlobReference(fileName)
.ExistsAsync();
return result;
}
public async Task<string> UploadFile(
string sourceFile, string containerName,
string destinationFile, string contentType) {
var container = _blobClient.GetContainerReference(containerName);
await container.CreateIfNotExistsAsync();
var blockBlob = container.GetBlockBlobReference(destinationFile);
blockBlob.Properties.ContentType = contentType;
var blockSize = 256 * 1024;
blockBlob.StreamWriteSizeInBytes = blockSize;
var bytesToUpload = (new FileInfo(sourceFile)).Length;
var fileSize = bytesToUpload;
if (bytesToUpload < blockSize) {
await blockBlob.UploadFromFileAsync(sourceFile);
} else {
var blockIds = new List<string>();
var index = 1;
long startPosition = 0;
long bytesUploaded = 0;
do {
var bytesToRead = Math.Min(blockSize, bytesToUpload);
var blobContents = new byte[bytesToRead];
using (var fs = new FileStream(sourceFile, FileMode.Open)) {
fs.Position = startPosition;
fs.Read(blobContents, 0, (int)bytesToRead);
}
var mre = new ManualResetEvent(false);
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));
Console.WriteLine("Now uploading block # " + index.ToString("d6"));
blockIds.Add(blockId);
await blockBlob.PutBlockAsync(blockId, new MemoryStream(blobContents), null);
bytesUploaded += bytesToRead;
bytesToUpload -= bytesToRead;
startPosition += bytesToRead;
index++;
var percentComplete = (double)bytesUploaded / (double)fileSize;
Console.WriteLine("Percent complete = " + percentComplete.ToString("P"));
mre.Set();
mre.WaitOne();
} while (bytesToUpload > 0);
Console.WriteLine("Now committing block list");
await blockBlob.PutBlockListAsync(blockIds);
blockBlob.Properties.ContentType = "audio/mpeg";
await blockBlob.SetPropertiesAsync();
Console.WriteLine("Blob uploaded completely.");
}
return $"{containerName}/{destinationFile}";
}
}
}

50
Services/DocHelpers.cs Normal file
View File

@@ -0,0 +1,50 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace retns.api.Services {
public class DocHelpers {
public static Task<string> ConvertToDocx(string fileName) {
return Task.Run(() => {
var outputFile = $"{fileName}.docx";
var processArgs = $"-d document --format=docx --output {outputFile} {fileName}";
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "unoconv",
Arguments = processArgs,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return outputFile;
});
}
public static Task<string> ConvertToHtml(string fileName, string outputFile) {
return Task.Run(() => {
//unoconv -d document --format=docx --output /tmp/test-case-2.doc.docx /tmp/test-case-2.doc
var processArgs = $"-d document --format=html --output {outputFile} {fileName}";
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "unoconv",
Arguments = processArgs,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
var result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return outputFile;
});
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace retns.api.Services.Extensions {
public static class DateTimeExtensions {
public static DateTime GetNextWeekday(this DateTime dt, DayOfWeek day) {
int daysToAdd = ((int)day - (int)dt.DayOfWeek + 7) % 7;
// TODO: Remove the -7 adddays!!!!
return dt.AddDays(-7).AddDays(daysToAdd);
}
public static DateTime GetThisMonday(this DateTime dt, DayOfWeek day = DayOfWeek.Monday) {
int diff = (7 + (dt.DayOfWeek - day)) % 7;
return dt.AddDays(-1 * diff).Date;
}
}
}

View File

@@ -0,0 +1,7 @@
using System;
namespace retns.api.Services.Extensions {
public static class ExtensionHolder {
}
}

View File

@@ -0,0 +1,158 @@
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using retns.api.Data.Models;
using System.Linq;
using System.Collections.Generic;
using retns.api.Data;
using System.IO;
using System.Globalization;
using retns.api.Services.Extensions;
using Microsoft.Extensions.Logging;
namespace retns.api.Services {
public class HomeworkFileParser {
private readonly AzureHelper _fileUploader;
private readonly HomeworkService _service;
private readonly ILogger<HomeworkFileParser> _logger;
public HomeworkFileParser(AzureHelper fileUploader, HomeworkService service, ILogger<HomeworkFileParser> logger) {
this._logger = logger;
this._fileUploader = fileUploader;
this._service = service;
}
public async Task<bool> ProcessFromUrl(string url, string sourceFilename) {
var extension = new FileInfo(sourceFilename).Extension;
using (var wc = new System.Net.WebClient()) {
string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + $".{extension}";
await wc.DownloadFileTaskAsync(new Uri(url), fileName);
if (System.IO.File.Exists(fileName)) {
if (extension.Equals(".doc")) {
fileName = await DocHelpers.ConvertToDocx(fileName);
}
if (System.IO.File.Exists(fileName)) {
var id = DateTime.Now.GetNextWeekday(DayOfWeek.Monday).ToString("ddMMyy");
await _createHtmlFile(id, fileName);
var week = await _processFile(id, fileName);
if (week != null) {
Console.WriteLine("Sending to cosmos");
await _service.Create(week);
return true;
}
}
}
}
return false;
}
private async Task<byte[]> _downloadFile(string url) {
using (var client = new HttpClient()) {
using (var result = await client.GetAsync(url)) {
if (result.IsSuccessStatusCode) {
return await result.Content.ReadAsByteArrayAsync();
}
}
}
return null;
}
private static DateTime _parseOrdinalDateTime(string dt) {
string[] expectedFormats = new[]
{
"d'st' MMMM yyyy",
"d'nd' MMMM yyyy",
"d'rd' MMMM yyyy",
"d'th' MMMM yyyy"
};
try {
return DateTime.ParseExact(dt, expectedFormats, null, DateTimeStyles.None);
} catch (Exception e) {
throw new InvalidOperationException("Not a valid DateTime string", e);
}
}
private void _processTable(Table node, ref HomeworkWeek week) {
//parse the subjects
week.Subjects = node.Descendants<TableRow>()
.First()
.Skip(2)
.Select(r => r.InnerText)
.ToList();
short dayIndex = 0;
foreach (var dow in Enum.GetValues(typeof(DayOfWeek))
.OfType<DayOfWeek>()
.ToList()
.Skip(1).Take(4)) {
var entries = node.Descendants<TableRow>()
.Skip(dayIndex + 1)
.First()
.Skip(2)
.Select(r => r.InnerText)
.ToArray();
var days = new Dictionary<string, string>();
short entryIndex = 0;
foreach (var entry in entries) {
try {
var subject = week.Subjects[entryIndex++];
days.Add(subject, entry);
} catch (Exception ex) {
Console.Error.WriteLine(ex.Message);
}
}
week.Days.Add(dow, days);
dayIndex++;
}
}
private Task<HomeworkWeek> _processFile(string id, string fileName) {
return Task.Run(() => {
var fi = new FileInfo(fileName);
var sb = new StringBuilder();
using (var doc = WordprocessingDocument.Open(fileName, false)) {
var week = new HomeworkWeek(id);
week.WeekCommencing = DateTimeExtensions.GetNextWeekday(DateTime.Now, DayOfWeek.Monday);
var notes = new StringBuilder();
var paragraphs = doc.MainDocumentPart.Document.Body.Elements().OfType<Paragraph>();
foreach (var paragraph in paragraphs) {
try {
//check if we got the date
var date = _parseOrdinalDateTime(paragraph.InnerText);
week.WeekCommencing = date;
continue;
} catch (Exception /*ex*/) {
// _logger.LogError(ex.Message);
}
notes.Append(paragraph.InnerText);
notes.Append(Environment.NewLine);
notes.Append(Environment.NewLine);
}
week.Notes = notes.ToString();
var table = doc.MainDocumentPart.Document.Body.Elements().OfType<Table>().FirstOrDefault();
if (table == null) return null;
_processTable(table, ref week);
return week;
}
});
}
private async Task<bool> _createHtmlFile(string id, string fileName) {
var outputFile = id + ".html";
var tempFile = Path.Combine(Path.GetTempPath(), outputFile);
var htmlFile = await DocHelpers.ConvertToHtml(fileName, tempFile);
if (File.Exists(htmlFile)) {
await _fileUploader.UploadFile(htmlFile, "html", outputFile, "text/html");
return true;
}
return false;
}
}
}

68
Startup.cs Normal file
View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using retns.api.Data;
using retns.api.Data.Models;
using retns.api.Data.Settings;
using retns.api.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace retns.homework.api {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.Configure<StorageSettings>(Configuration.GetSection("StorageSettings"));
services.AddScoped<HomeworkFileParser>();
services.AddScoped<AzureHelper>();
services.AddScoped<HomeworkService>();
var storageSettings = Configuration.GetSection(nameof(StorageSettings)).Get<StorageSettings>();
services.AddHttpClient("AzureClient", client => {
client.BaseAddress = new Uri(storageSettings.CdnUrl);
});
services.AddCors(options => {
options.AddPolicy(
"AllowAllOrigins",
builder => builder.AllowAnyOrigin()
.AllowAnyHeader());
});
services.AddMvc(options => {
options.OutputFormatters.OfType<StringOutputFormatter>().Single().SupportedMediaTypes.Add("text/html");
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors(builder => {
builder.AllowAnyOrigin().AllowAnyHeader();
});
app.UseMvc();
}
}
}

8
appsettings.json Normal file
View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

18
retns.homework.api.csproj Normal file
View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack.NetCore" Version="1.5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.8.1" />
<PackageReference Include="MongoDB.Driver" Version="2.7.3" />
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
</ItemGroup>
</Project>