Skip to content

migrate to asp.net core 3.0 #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Oct 11, 2019
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b3c73f2
add retryHelper
WeihanLi Sep 11, 2019
95efa36
update to aspnetcore3.0
WeihanLi Sep 24, 2019
c40834c
disable dotnet build
WeihanLi Sep 24, 2019
4347c22
update Dockerfile
WeihanLi Sep 24, 2019
7e1573f
fix error for asp.net core 3.0
WeihanLi Sep 24, 2019
f05b537
use sqlServer instead of mysql
WeihanLi Sep 24, 2019
f0dd9b3
add Globalization Invariant Mode config
WeihanLi Sep 24, 2019
9f707df
install icu-lib
WeihanLi Sep 24, 2019
4d07d60
update DOckerfile, set DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
WeihanLi Sep 25, 2019
9ebe52e
update swagger/update test to 3.0
WeihanLi Sep 25, 2019
619f796
update entityFramework extension
WeihanLi Sep 25, 2019
cd02027
add cleanData.sql
WeihanLi Sep 25, 2019
2f4e696
downgrade ef to 2.x
WeihanLi Sep 26, 2019
de4321e
fix init notice data
WeihanLi Sep 26, 2019
18da9fd
update swagger version
WeihanLi Oct 8, 2019
96046da
fix init data, only supper for admin user
WeihanLi Oct 8, 2019
6198322
integrate with swagger
WeihanLi Oct 8, 2019
f614ac9
remove admin route
WeihanLi Oct 8, 2019
c760901
fix test
WeihanLi Oct 8, 2019
5b841d2
use swagger before useRounting
WeihanLi Oct 10, 2019
fdd2835
update build agent image
WeihanLi Oct 10, 2019
d3c4bec
output dotnet info on ci build
WeihanLi Oct 10, 2019
332ae14
update pipeline config
WeihanLi Oct 10, 2019
64e7511
update the method get framework version
WeihanLi Oct 10, 2019
6e5a824
update footer
WeihanLi Oct 10, 2019
c147e77
update ChatBotHelper
WeihanLi Oct 10, 2019
cf23e66
update mvcSimplePager
WeihanLi Oct 10, 2019
6a55519
update dependency
WeihanLi Oct 11, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@

# Build results
[Dd]ebug/
[Oo]ut/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
18 changes: 2 additions & 16 deletions ActivityReservation.API.Test/APITestFixture.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using System;
using System.Linq;
using System.Net.Http;
using System.Net.NetworkInformation;
using ActivityReservation.Database;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using WeihanLi.Common.Helpers;
using Xunit;

namespace ActivityReservation.API.Test
@@ -23,7 +22,7 @@ public class APITestFixture : IDisposable

public APITestFixture()
{
var baseUrl = $"http://localhost:{GetRandomPort()}";
var baseUrl = $"http://localhost:{NetHelper.GetRandomPort()}";
_server = WebHost.CreateDefaultBuilder()
.UseUrls(baseUrl)
.UseStartup<TestStartup>()
@@ -66,19 +65,6 @@ public void Dispose()

Console.WriteLine("test end");
}

private static int GetRandomPort()
{
var random = new Random();
var randomPort = random.Next(10000, 65535);

while (IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Any(p => p.Port == randomPort))
{
randomPort = random.Next(10000, 65535);
}

return randomPort;
}
}

[CollectionDefinition("APITestCollection")]
11 changes: 4 additions & 7 deletions ActivityReservation.API.Test/ActivityReservation.API.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0" />

<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.1.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Threading.Tasks;
using ActivityReservation.Database;
using ActivityReservation.Events;
using WeihanLi.Common;
using WeihanLi.Common.Event;

namespace ActivityReservation.API.Test.MockServices
{
internal class MockNoticeViewEventHandler : IEventHandler<NoticeViewEvent>
{
public async Task Handle(NoticeViewEvent @event)
{
await DependencyResolver.Current.TryInvokeServiceAsync<ReservationDbContext>(async dbContext =>
{
var notice = await dbContext.Notices.FindAsync(@event.NoticeId);
if (null != notice)
{
notice.NoticeVisitCount += 1;
await dbContext.SaveChangesAsync();
}
});
}
}
}
184 changes: 184 additions & 0 deletions ActivityReservation.API.Test/TestDataInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ActivityReservation.Database;
using ActivityReservation.Models;
using ActivityReservation.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using WeihanLi.Common.Helpers;

namespace ActivityReservation.API.Test
{
internal class TestDataInitializer
{
public static void Initialize(IServiceProvider serviceProvider)
{
IReadOnlyCollection<SystemSettings> settings;

using (var scope = serviceProvider.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ReservationDbContext>();
dbContext.Database.EnsureCreated();
if (!dbContext.Users.AsNoTracking().Any())
{
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "admin",
UserPassword = SecurityHelper.SHA256("Admin888"),
IsSuper = true
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "Alice",
UserPassword = SecurityHelper.SHA256("Test1234"),
IsSuper = false
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "test",
UserPassword = SecurityHelper.SHA256("Test1234"),
IsSuper = false
});

var blockTypes = new List<BlockType>
{
new BlockType {TypeId = Guid.NewGuid(), TypeName = "联系方式"},
new BlockType {TypeId = Guid.NewGuid(), TypeName = "IP地址"},
new BlockType {TypeId = Guid.NewGuid(), TypeName = "预约人姓名"}
};
dbContext.BlockTypes.AddRange(blockTypes);

var placeId = Guid.NewGuid();
var placeId1 = Guid.NewGuid();
//Places init
dbContext.ReservationPlaces.AddRange(new[] {
new ReservationPlace { PlaceId = placeId, PlaceName = "第一多功能厅", UpdateBy = "System", PlaceIndex = 0,MaxReservationPeriodNum = 2 },
new ReservationPlace { PlaceId = placeId1, PlaceName = "第二多功能厅", UpdateBy = "System", PlaceIndex = 1,MaxReservationPeriodNum = 2}}
);

dbContext.ReservationPeriods.AddRange(new[]
{
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 0,
PeriodTitle = "8:00~10:00",
PeriodDescription = "8:00~10:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "10:00~12:00",
PeriodDescription = "10:00~12:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 2,
PeriodTitle = "13:00~16:00",
PeriodDescription = "13:00~16:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "08:00~18:00",
PeriodDescription = "08:00~18:00",
PlaceId = placeId1,
CreateBy = "System",
CreateTime = DateTime.UtcNow.AddSeconds(3),
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
});
var notice = new Notice()
{
NoticeId = Guid.NewGuid(),
CheckStatus = true,
NoticeTitle = "测试公告",
NoticeCustomPath = "test-notice",
NoticePath = "test-notice.html",
NoticeContent = "测试一下",
NoticePublishTime = DateTime.UtcNow,
NoticeDesc = "测试一下",
NoticePublisher = "System"
};
dbContext.Notices.Add(notice);

//sys settings init
settings = new List<SystemSettings>
{
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemTitle",
DisplayName = "系统标题",
SettingValue = "活动室预约系统"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemKeywords",
DisplayName = "系统关键词",
SettingValue = "预约,活动室,预定,reservation"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemDescription",
DisplayName = "系统简介",
SettingValue = "活动室预约系统是一个基于ASP.NET MVC 开发的一个在线预约系统。"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactPhone",
DisplayName = "系统联系人联系电话",
SettingValue = "13245642365"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactEmail",
DisplayName = "系统联系邮箱",
SettingValue = "weihanli@outlook.com"
}
};
dbContext.SystemSettings.AddRange(settings);

dbContext.SaveChanges();
}
else
{
settings = dbContext.SystemSettings.AsNoTracking().ToArray();
}
}

if (settings.Count > 0) // init settings cache
{
var applicationSettingService = serviceProvider.GetRequiredService<IApplicationSettingService>();
applicationSettingService.AddSettings(settings.ToDictionary(s => s.SettingName, s => s.SettingValue));
}
}
}
}
36 changes: 13 additions & 23 deletions ActivityReservation.API.Test/TestStartup.cs
Original file line number Diff line number Diff line change
@@ -36,8 +36,9 @@ public TestStartup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options =>
services.AddControllers()
.AddApplicationPart(typeof(API.ApiControllerBase).Assembly)
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; // 设置时区为 UTC
@@ -51,8 +52,6 @@ public void ConfigureServices(IServiceCollection services)
// addDbContext
services.AddDbContextPool<ReservationDbContext>(options => options.UseInMemoryDatabase("Reservation"));

services.TryAddSingleton<ICacheClient, MockRedisCacheClient>();

services.AddHttpClient<TencentCaptchaHelper>(client => client.Timeout = TimeSpan.FromSeconds(3))
.ConfigurePrimaryHttpMessageHandler(() => new NoProxyHttpClientHandler());
services.AddTencentCaptchaHelper(options =>
@@ -69,14 +68,17 @@ public void ConfigureServices(IServiceCollection services)

// registerApplicationSettingService
services.TryAddSingleton<IApplicationSettingService, ApplicationSettingInMemoryService>();
// register access control service
services.AddAccessControlHelper<Filters.AdminPermissionRequireStrategy, Filters.AdminOnlyControlAccessStrategy>();

services.TryAddSingleton<CaptchaVerifyHelper>();

services.AddSingleton<IEventBus, EventBus>();
services.AddSingleton<IEventStore, EventStoreInMemory>();
//register EventHandlers
services.AddSingleton<OperationLogEventHandler>();
services.AddSingleton<NoticeViewEventHandler>();
services.AddSingleton<MockNoticeViewEventHandler>();

services.TryAddSingleton<ICacheClient, MockRedisCacheClient>();

// SetDependencyResolver
DependencyResolver.SetDependencyResolver(services);
@@ -85,27 +87,15 @@ public void ConfigureServices(IServiceCollection services)
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IEventBus eventBus)
{
eventBus.Subscribe<NoticeViewEvent, NoticeViewEventHandler>(); // 公告
eventBus.Subscribe<OperationLogEvent, OperationLogEventHandler>(); //操作日志

app.UseMvc(routes =>
app.UseRouting();
app.UseEndpoints(endpoints =>
{
routes.MapRoute("Notice", "/Notice/{path}.html", new
{
controller = "Home",
action = "NoticeDetails"
});

routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}");
endpoints.MapControllers();
});

// initialize
app.ApplicationServices.Initialize();
eventBus.Subscribe<NoticeViewEvent, MockNoticeViewEventHandler>();
TestDataInitializer.Initialize(app.ApplicationServices);
}
}
}
5 changes: 0 additions & 5 deletions ActivityReservation.API.Test/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{
"KeyVault": {
"Name": "weihanli",
"ClientId": "31e1c36d-5d98-4a45-9553-33b7fc871a66",
"ClientSecret": "4VdVPsvDO+rwzQ6rOWxN2oAA4cgBlvqcWyPoiMcxW3Y="
},
"ConnectionStrings": {
"Redis": "127.0.0.1"
},
2 changes: 1 addition & 1 deletion ActivityReservation.API/APIControllerBase.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ public abstract class ApiControllerBase : ControllerBase
{
protected readonly ILogger Logger;

public ApiControllerBase(ILogger logger)
protected ApiControllerBase(ILogger logger)
{
Logger = logger;
}
2 changes: 1 addition & 1 deletion ActivityReservation.API/ActivityReservation.API.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ActivityReservation.Helper\ActivityReservation.Helper.csproj" />
2 changes: 1 addition & 1 deletion ActivityReservation.Clients/WxAppClient/miniprogram/app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PagedListData } from './../models/PagedListData';
import { RetryHelper } from '../utils/RetryHelper';

export class BaseService<TModel>{
protected readonly apiBaseUrl: string = "https://service-balxf7hr-1251288923.ap-shanghai.apigateway.myqcloud.com/release/reservationWxAppGateway";
@@ -25,6 +26,9 @@ export class BaseService<TModel>{
let result = <PagedListData<TModel>>response.data;
callback(result);
wx.hideLoading();
},
fail: (err)=>{

}
});
}
@@ -40,6 +44,9 @@ export class BaseService<TModel>{
wx.hideLoading();
let result = <Array<TModel>>response.data;
callback(result);
},
fail: (err)=>{

}
});
}
@@ -62,6 +69,9 @@ export class BaseService<TModel>{
wx.hideLoading();
let result = <TModel><any>response.data;
callback(result);
},
fail: (err)=>{

}
});
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseService } from './BaseService';
import { ReservationPlace } from '../models/ReservationPlace';
import { ReservationPeriod } from '../models/ReservationPeriod';
import { RetryHelper } from '../utils/RetryHelper';

export class ReservationPlaceService extends BaseService<ReservationPlace>{

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

import { BaseService } from './BaseService';
import { Reservation } from '../models/Reservation';
import { RetryHelper } from '../utils/RetryHelper';


export class ReservationService extends BaseService<Reservation>{

@@ -10,7 +12,7 @@ export class ReservationService extends BaseService<Reservation>{

public NewReservation(callback:(result:any)=>void,reservation: Reservation, captchaType: string, captcha: string){
wx.showLoading({
title: "loading..."
title: "loading..."
});
let url = `${this.apiBaseUrl}/api/reservation`;
wx.request({
@@ -27,6 +29,9 @@ export class ReservationService extends BaseService<Reservation>{
wx.hideLoading();
let result = <any>response.data;
callback(result);
},
fail: (err)=>{

}
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export class RetryHelper {
public static tryInvoke(callback: () => any, validFunc: (res: any) => boolean, maxRetryTimes: number = 5, logErrorMinTimes: number = 1): any {
let timer = 0;
let isSucceed = false;
while (!isSucceed && timer <= maxRetryTimes) {
try {
let result = callback();
isSucceed = validFunc(result);
if (!isSucceed) {
timer++;
}
return result;
} catch (error) {
if(timer++ >= logErrorMinTimes){
console.error(`retry failed, retry times: ${timer}, error: ${error}`);
}
}
}
return null;
};

public static async tryInvokeAsync(callback: () => Promise<any>, validFunc: (res: any) => boolean, maxRetryTimes: number = 5, logErrorMinTimes: number = 1) {
let timer = 0;
let isSucceed = false;
while (!isSucceed && timer <= maxRetryTimes) {
try {
let result = await callback();
isSucceed = validFunc(result);
if (!isSucceed) {
timer++;
}
return result;
} catch (error) {
if(timer++ >= logErrorMinTimes){
console.error(`retry failed, retry times: ${timer}, error: ${error}`);
}
}
}
return null;
};
}
4 changes: 2 additions & 2 deletions ActivityReservation.Common/ActivityReservation.Common.csproj
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="WeihanLi.Common" Version="1.0.24.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.1.0" />
<PackageReference Include="WeihanLi.Common" Version="1.0.24.3" />
</ItemGroup>
</Project>
8 changes: 3 additions & 5 deletions ActivityReservation.Common/ChatBotHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
@@ -36,9 +35,8 @@ public ChatBotHelper(HttpClient httpClient, ILogger<ChatBotHelper> logger)
/// 获取机器人回复【异步】
/// </summary>
/// <param name="request">请求</param>
/// <param name="cancellationToken"></param>
/// <returns>回复信息</returns>
public async Task<string> GetBotReplyAsync(string request, CancellationToken cancellationToken = default)
public async Task<string> GetBotReplyAsync(string request)
{
if (request.IsNullOrWhiteSpace())
{
@@ -47,7 +45,7 @@ public async Task<string> GetBotReplyAsync(string request, CancellationToken can
try
{
using (var response = await _httpClient.
GetAsync(string.Format(QingyunkeRequestUrlFormat, request.UrlEncode()), cancellationToken))
GetAsync(string.Format(QingyunkeRequestUrlFormat, request.UrlEncode())))
{
var responseText = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(responseText))
@@ -64,7 +62,7 @@ public async Task<string> GetBotReplyAsync(string request, CancellationToken can
}
catch (Exception ex)
{
_logger.Error(ex);
_logger.LogError(ex, "调用 Qingyunke API 出错");
}
return "error";
}
Original file line number Diff line number Diff line change
@@ -5,31 +5,10 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="DALCollection.generated.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>DALCollection.tt</DependentUpon>
</Compile>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ActivityReservation.Models\ActivityReservation.Models.csproj">
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Update="DALCollection.generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>DALCollection.tt</DependentUpon>
</Compile>
<None Update="DALCollection.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>DALCollection.generated.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion ActivityReservation.DataAccess/ReservationDbContext.cs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Notice>().HasQueryFilter(x => !x.IsDeleted);
modelBuilder.Entity<Reservation>().HasQueryFilter(r => r.ReservationStatus != ReservationStatus.Deleted);

modelBuilder.Entity<Notice>().HasIndex(x => x.NoticeCustomPath); // path 设置索引
// modelBuilder.Entity<Notice>().HasIndex(x => x.NoticeCustomPath); // path
}

public virtual DbSet<User> Users { get; set; }
16 changes: 8 additions & 8 deletions ActivityReservation.Helper/ActivityReservation.Helper.csproj
Original file line number Diff line number Diff line change
@@ -2,16 +2,16 @@
<PropertyGroup>
<AssemblyName>ActivityReservation.Helper</AssemblyName>
<RootNamespace>ActivityReservation</RootNamespace>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="WeihanLi.AspNetMvc.AccessControlHelper" Version="1.8.2" />
<PackageReference Include="WeihanLi.AspNetMvc.MvcSimplePager" Version="1.3.0" />
<PackageReference Include="WeihanLi.Npoi" Version="1.3.8" />
<PackageReference Include="WeihanLi.Redis" Version="1.5.6.9" />
<PackageReference Include="WeihanLi.Web.Extensions" Version="1.0.0-preview-20190630-113152" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="WeihanLi.AspNetMvc.AccessControlHelper" Version="1.9.0" />
<PackageReference Include="WeihanLi.AspNetMvc.MvcSimplePager" Version="1.4.0" />
<PackageReference Include="WeihanLi.Npoi" Version="1.4.0" />
<PackageReference Include="WeihanLi.Redis" Version="1.5.6.10" />
<PackageReference Include="WeihanLi.Web.Extensions" Version="1.0.0-preview-20191011-092336" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ActivityReservation.Business\ActivityReservation.Business.csproj" />
272 changes: 144 additions & 128 deletions ActivityReservation.Helper/Helpers/DatabaseInitializer.cs
Original file line number Diff line number Diff line change
@@ -20,146 +20,162 @@ public static void Initialize(this IServiceProvider serviceProvider)
{
var dbContext = scope.ServiceProvider.GetRequiredService<ReservationDbContext>();
dbContext.Database.EnsureCreated();
if (!dbContext.Users.AsNoTracking().Any())
using (var transaction = dbContext.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
dbContext.Users.Add(new User
if (!dbContext.Users.AsNoTracking().Any())
{
UserId = Guid.NewGuid(),
UserName = "admin",
UserPassword = SecurityHelper.SHA256("Admin888"),
IsSuper = true
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "Alice",
UserPassword = SecurityHelper.SHA256("Test1234"),
IsSuper = true
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "admin",
UserPassword = SecurityHelper.SHA256("Admin888"),
IsSuper = true
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "Alice",
UserPassword = SecurityHelper.SHA256("Test1234"),
IsSuper = false
});
dbContext.Users.Add(new User
{
UserId = Guid.NewGuid(),
UserName = "test",
UserPassword = SecurityHelper.SHA256("Test1234"),
IsSuper = false
});

var blockTypes = new List<BlockType>
var blockTypes = new List<BlockType>
{
new BlockType {TypeId = Guid.NewGuid(), TypeName = "联系方式"},
new BlockType {TypeId = Guid.NewGuid(), TypeName = "IP地址"},
new BlockType {TypeId = Guid.NewGuid(), TypeName = "预约人姓名"}
};
dbContext.BlockTypes.AddRange(blockTypes);
dbContext.BlockTypes.AddRange(blockTypes);

var placeId = Guid.NewGuid();
var placeId1 = Guid.NewGuid();
//Places init
dbContext.ReservationPlaces.AddRange(new[] {
new ReservationPlace { PlaceId = placeId, PlaceName = "第一多功能厅", UpdateBy = "System", PlaceIndex = 0,MaxReservationPeriodNum = 2 },
new ReservationPlace { PlaceId = placeId1, PlaceName = "第二多功能厅", UpdateBy = "System", PlaceIndex = 1,MaxReservationPeriodNum = 2}});
dbContext.ReservationPeriods.AddRange(new[]
{
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 3,
PeriodTitle = "8:00~10:00",
PeriodDescription = "8:00~10:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "10:00~12:00",
PeriodDescription = "10:00~12:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 2,
PeriodTitle = "13:00~16:00",
PeriodDescription = "13:00~16:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "08:00~18:00",
PeriodDescription = "08:00~18:00",
PlaceId = placeId1,
CreateBy = "System",
CreateTime = DateTime.UtcNow.AddSeconds(3),
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
});
var notice = new Notice()
{
NoticeId = Guid.NewGuid(),
CheckStatus = true,
NoticeTitle = "测试公告",
NoticeCustomPath = "test-notice",
NoticePublishTime = DateTime.UtcNow,
NoticeDesc = "测试一下",
NoticePublisher = "System"
};
dbContext.Notices.Add(notice);
var placeId = Guid.NewGuid();
var placeId1 = Guid.NewGuid();
//Places init
dbContext.ReservationPlaces.AddRange(new[] {
new ReservationPlace { PlaceId = placeId, PlaceName = "第一多功能厅", UpdateBy = "System", PlaceIndex = 0,MaxReservationPeriodNum = 2 },
new ReservationPlace { PlaceId = placeId1, PlaceName = "第二多功能厅", UpdateBy = "System", PlaceIndex = 1,MaxReservationPeriodNum = 2}}
);

//sys settings init
settings = new List<SystemSettings>
{
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemTitle",
DisplayName = "系统标题",
SettingValue = "活动室预约系统"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemKeywords",
DisplayName = "系统关键词",
SettingValue = "预约,活动室,预定,reservation"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemDescription",
DisplayName = "系统简介",
SettingValue = "活动室预约系统是一个基于ASP.NET MVC 开发的一个在线预约系统。"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactPhone",
DisplayName = "系统联系人联系电话",
SettingValue = "13245642365"
},
new SystemSettings
dbContext.ReservationPeriods.AddRange(new[]
{
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 3,
PeriodTitle = "8:00~10:00",
PeriodDescription = "8:00~10:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "10:00~12:00",
PeriodDescription = "10:00~12:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 2,
PeriodTitle = "13:00~16:00",
PeriodDescription = "13:00~16:00",
PlaceId = placeId,
CreateBy = "System",
CreateTime = DateTime.UtcNow,
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
new ReservationPeriod
{
PeriodId = Guid.NewGuid(),
PeriodIndex = 1,
PeriodTitle = "08:00~18:00",
PeriodDescription = "08:00~18:00",
PlaceId = placeId1,
CreateBy = "System",
CreateTime = DateTime.UtcNow.AddSeconds(3),
UpdateBy = "System",
UpdateTime = DateTime.UtcNow
},
});
var notice = new Notice()
{
NoticeId = Guid.NewGuid(),
CheckStatus = true,
NoticeTitle = "测试公告",
NoticeCustomPath = "test-notice",
NoticePath = "test-notice.html",
NoticeContent = "测试一下",
NoticePublishTime = DateTime.UtcNow,
NoticeDesc = "测试一下",
NoticePublisher = "System"
};
dbContext.Notices.Add(notice);

//sys settings init
settings = new List<SystemSettings>
{
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemTitle",
DisplayName = "系统标题",
SettingValue = "活动室预约系统"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemKeywords",
DisplayName = "系统关键词",
SettingValue = "预约,活动室,预定,reservation"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemDescription",
DisplayName = "系统简介",
SettingValue = "活动室预约系统是一个基于ASP.NET MVC 开发的一个在线预约系统。"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactPhone",
DisplayName = "系统联系人联系电话",
SettingValue = "13245642365"
},
new SystemSettings
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactEmail",
DisplayName = "系统联系邮箱",
SettingValue = "weihanli@outlook.com"
}
};
dbContext.SystemSettings.AddRange(settings);

dbContext.SaveChanges();

transaction.Commit();
}
else
{
SettingId = Guid.NewGuid(),
SettingName = "SystemContactEmail",
DisplayName = "系统联系邮箱",
SettingValue = "weihanli@outlook.com"
settings = dbContext.SystemSettings.AsNoTracking().ToArray();
}
};
dbContext.SystemSettings.AddRange(settings);

dbContext.SaveChanges();
}
else
{
settings = dbContext.SystemSettings.AsNoTracking().ToArray();
}
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ActivityReservation.Helper\ActivityReservation.Helper.csproj" />
12 changes: 6 additions & 6 deletions ActivityReservation/ActivityReservation.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0" />
<!--<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />-->
<PackageReference Include="Sentry.Extensions.Logging" Version="1.2.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />
<PackageReference Include="WeihanLi.Common.Logging.Serilog" Version="1.0.23.8-preview-20190802-105729" />
</ItemGroup>
<ItemGroup>
3 changes: 1 addition & 2 deletions ActivityReservation/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -267,8 +267,7 @@ public async Task<IActionResult> Chat(string msg)
}
return Ok(new
{
text = await HttpContext.RequestServices.GetService<ChatBotHelper>()
.GetBotReplyAsync(msg, HttpContext.RequestAborted)
text = await HttpContext.RequestServices.GetService<ChatBotHelper>().GetBotReplyAsync(msg)
});
}

15 changes: 7 additions & 8 deletions ActivityReservation/Program.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ActivityReservation
{
public class Program
{
public static void Main(string[] args)
{
var host = WebHost.CreateDefaultBuilder(args)
var host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) =>
{
var builtConfig = builder.Build();
@@ -24,13 +24,12 @@ public static void Main(string[] args)
;
}
})
.UseStartup<Startup>()
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.UseStartup<Startup>();
})
.Build();
host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
84 changes: 43 additions & 41 deletions ActivityReservation/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System;
using System.IO;
using System.Threading.Tasks;
using ActivityReservation.API;
using ActivityReservation.Business;
using ActivityReservation.Common;
using ActivityReservation.Database;
using ActivityReservation.Events;
using ActivityReservation.Extensions;
using ActivityReservation.Helpers;
using ActivityReservation.Models;
using ActivityReservation.Services;
using ActivityReservation.ViewModels;
using Microsoft.AspNetCore.Authentication.Cookies;
@@ -21,12 +18,12 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Serilog;
using StackExchange.Redis;
using Swashbuckle.AspNetCore.Swagger;
using WeihanLi.Common;
using WeihanLi.Common.Event;
using WeihanLi.Common.Helpers;
@@ -44,20 +41,23 @@ namespace ActivityReservation
{
public class Startup
{
public Startup(IConfiguration configuration)
public Startup(IConfiguration configuration, IWebHostEnvironment hostEnvironment)
{
HostEnvironment = hostEnvironment;
Configuration = configuration.ReplacePlaceholders();
}

public IWebHostEnvironment HostEnvironment { get; }

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.AddHealthChecks();

services.AddMvc()
.AddJsonOptions(options =>
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; // 设置时区为 UTC
@@ -66,12 +66,6 @@ public void ConfigureServices(IServiceCollection services)
})
.SetCompatibilityVersion(CompatibilityVersion.Latest);

// DataProtection persist in redis
services.AddDataProtection()
.SetApplicationName(ApplicationHelper.ApplicationName)
.PersistKeysToStackExchangeRedis(() => DependencyResolver.Current.ResolveService<IConnectionMultiplexer>().GetDatabase(5), "DataProtection-Keys")
;

//Cookie Authentication
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
@@ -86,16 +80,7 @@ public void ConfigureServices(IServiceCollection services)
});

// addDbContext
services.AddDbContextPool<ReservationDbContext>(option => option.UseMySql(Configuration.GetConnectionString("Reservation")), 100);
services.AddRedisConfig(options =>
{
options.RedisServers = new[]
{
new RedisServerConfiguration(Configuration.GetConnectionString("Redis")),
};
options.CachePrefix = "ActivityReservation"; // ApplicationHelper.ApplicationName by default
options.DefaultDatabase = 2;
});
services.AddDbContextPool<ReservationDbContext>(option => option.UseSqlServer(Configuration.GetConnectionString("Reservation")), 100);

services.AddHttpClient<GoogleRecaptchaHelper>(client =>
{
@@ -125,7 +110,7 @@ public void ConfigureServices(IServiceCollection services)

services.AddHttpClient<ChatBotHelper>(client =>
{
client.Timeout = TimeSpan.FromSeconds(3);
client.Timeout = TimeSpan.FromSeconds(5);
})
.ConfigurePrimaryHttpMessageHandler(() => new NoProxyHttpClientHandler());
services.TryAddSingleton<ChatBotHelper>();
@@ -136,16 +121,24 @@ public void ConfigureServices(IServiceCollection services)

services.TryAddSingleton<CaptchaVerifyHelper>();

services.AddSwaggerGen(options =>
services.AddRedisConfig(options =>
{
options.SwaggerDoc(ApplicationHelper.ApplicationName, new Info { Title = "活动室预约系统 API", Version = "1.0" });

options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{typeof(Notice).Assembly.GetName().Name}.xml"));
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{typeof(NoticeController).Assembly.GetName().Name}.xml"), true);
options.RedisServers = new[]
{
new RedisServerConfiguration(Configuration.GetConnectionString("Redis") ?? "127.0.0.1"),
};
options.CachePrefix = "ActivityReservation"; // ApplicationHelper.ApplicationName by default
options.DefaultDatabase = 2;
});

// DataProtection persist in redis
services.AddDataProtection()
.SetApplicationName(ApplicationHelper.ApplicationName)
.PersistKeysToStackExchangeRedis(() => DependencyResolver.Current.ResolveService<IConnectionMultiplexer>().GetDatabase(5), "DataProtection-Keys")
;
services.AddSingleton<IEventBus, RedisEventBus>();
services.AddSingleton<IEventStore, EventStoreInRedis>();

//register EventHandlers
services.AddSingleton<OperationLogEventHandler>();
services.AddSingleton<NoticeViewEventHandler>();
@@ -185,17 +178,24 @@ public void ConfigureServices(IServiceCollection services)
options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All;
});


services.Configure<GiteeStorageOptions>(Configuration.GetSection("Storage:Gitee"));
services.AddHttpClient<IStorageProvider, GiteeStorageProvider>();
services.TryAddSingleton<IStorageProvider, GiteeStorageProvider>();


services.AddSwaggerGen(options =>
{
options.SwaggerDoc(ApplicationHelper.ApplicationName, new Microsoft.OpenApi.Models.OpenApiInfo { Title = "活动室预约系统 API", Version = "1.0" });

options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(Models.Notice).Assembly.GetName().Name}.xml"));
options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(API.NoticeController).Assembly.GetName().Name}.xml"), true);
});

// SetDependencyResolver
DependencyResolver.SetDependencyResolver(services);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IEventBus eventBus)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IEventBus eventBus)
{
eventBus.Subscribe<NoticeViewEvent, NoticeViewEventHandler>(); // 公告
eventBus.Subscribe<OperationLogEvent, OperationLogEventHandler>(); //操作日志
@@ -246,33 +246,35 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
app.UseHealthCheck("/health");

app.UseStaticFiles();

app.UseSwagger()
.UseSwaggerUI(c =>
{
// c.RoutePrefix = string.Empty; //
c.SwaggerEndpoint($"/swagger/{ApplicationHelper.ApplicationName}/swagger.json", "活动室预约系统 API");
c.DocumentTitle = "活动室预约系统 API";
});

app.UseRouting();

app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());

app.UseRequestLog();
app.UsePerformanceLog();

app.UseAuthentication();
app.UseMvc(routes =>
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
routes.MapRoute("Notice", "/Notice/{path}.html", new
endpoints.MapControllers();
endpoints.MapControllerRoute("Notice", "/Notice/{path}.html", new
{
controller = "Home",
action = "NoticeDetails"
});

routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}");
endpoints.MapControllerRoute(name: "areaRoute", "{area:exists}/{controller=Home}/{action=Index}");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

// initialize
19 changes: 11 additions & 8 deletions ActivityReservation/Views/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
@@ -43,20 +43,23 @@
<div class="main-content">@RenderBody()</div>
<hr class="hidden-print" />
<footer class="hidden-print">
<p>&copy; @DateTime.UtcNow.Year - @(applicationSettings.GetSettingValue("SystemTitle")) &nbsp;&nbsp;&nbsp; @Html.ActionLink("后台登录", "Login", new { controller = "Account", area = "Admin" })</p>
<p>&copy; @DateTime.UtcNow.Year - @(applicationSettings.GetSettingValue("SystemTitle")) &nbsp;&nbsp;&nbsp; @Html.ActionLink("后台管理", "Login", new { controller = "Account", area = "Admin" })</p>
<p>Powered by @System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription </p>
</footer>
</div>
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-86200565-1', 'auto');
ga('send', 'pageview');
ga('create', 'UA-86200565-1', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
<!-- End Google Analytics -->
<environment names="Development">
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
10 changes: 10 additions & 0 deletions CleanData.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DROP TABLE tabNotice
DROP TABLE tabBlockType
DROP TABLE tabBlockEntity
DROP TABLE tabUser
DROP TABLE tabSystemSettings
DROP TABLE tabReservation
DROP TABLE tabReservationPeriod
DROP TABLE tabDisablePeriod
DROP TABLE tabNotice
DROP TABLE tabReservationPlace
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<VersionMajor>2</VersionMajor>
<VersionMajor>3</VersionMajor>
<VersionMinor>0</VersionMinor>
<VersionPatch>0</VersionPatch>
<VersionRevision>0</VersionRevision>
16 changes: 12 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM microsoft/dotnet:2.2-sdk-alpine AS build-env
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-alpine AS build-env
WORKDIR /src

# Copy csproj and restore as distinct layers
@@ -11,16 +11,24 @@ COPY ActivityReservation.WechatAPI/*.csproj ActivityReservation.WechatAPI/
COPY ActivityReservation.AdminLogic/*.csproj ActivityReservation.AdminLogic/
COPY ActivityReservation.API/*.csproj ActivityReservation.API/
COPY ActivityReservation/ActivityReservation.csproj ActivityReservation/
RUN dotnet restore ActivityReservation/ActivityReservation.csproj

# RUN dotnet restore ActivityReservation/ActivityReservation.csproj
## diff between netcore2.2 and netcore3.0
WORKDIR /src/ActivityReservation
RUN dotnet restore

# copy everything and build
COPY . .
RUN dotnet publish -c Release -o out ActivityReservation/ActivityReservation.csproj

# build runtime image
FROM microsoft/dotnet:2.2-aspnetcore-runtime-alpine
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine

RUN apk add libgdiplus --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted && \
apk add terminus-font
apk add terminus-font && \
apk add icu-libs
# https://www.abhith.net/blog/docker-sql-error-on-aspnet-core-alpine/
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
LABEL Maintainer="WeihanLi"
WORKDIR /app
COPY --from=build-env /src/ActivityReservation/out .
4 changes: 3 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -11,14 +11,16 @@ trigger:
- /docs/

pool:
vmImage: 'Ubuntu 16.04'
vmImage: 'ubuntu-latest'

variables:
tagName: '$(Build.BuildNumber)'
latestImageName: '$(dockerId)/activityreservation:latest'
imageName: '$(dockerId)/activityreservation:$(tagName)'

steps:
- script: dotnet --info
displayName: 'dotnet info'

- script: dotnet build -c Release
displayName: 'dotnet build'