Merge branch 'master' of github.com:hudingwen/Blog.Core

This commit is contained in:
hudingwen 2021-07-12 00:05:34 +08:00
commit 4f9d935238
36 changed files with 932 additions and 266 deletions

View File

@ -140,6 +140,26 @@
<param name="response">数据</param>
<returns></returns>
</member>
<member name="P:Blog.Core.Model.MessageModel.status">
<summary>
状态码
</summary>
</member>
<member name="P:Blog.Core.Model.MessageModel.success">
<summary>
操作是否成功
</summary>
</member>
<member name="P:Blog.Core.Model.MessageModel.msg">
<summary>
返回信息
</summary>
</member>
<member name="P:Blog.Core.Model.MessageModel.response">
<summary>
返回数据集合
</summary>
</member>
<member name="P:Blog.Core.Model.Models.Advertisement.ImgUrl">
<summary>
广告图片

View File

@ -9,12 +9,12 @@
博客管理
</summary>
</member>
<member name="M:Blog.Core.Controllers.BlogController.#ctor(Blog.Core.IServices.IBlogArticleServices,Microsoft.Extensions.Logging.ILogger{Blog.Core.Controllers.BlogController})">
<member name="M:Blog.Core.Controllers.BlogController.#ctor(Microsoft.Extensions.Logging.ILogger{Blog.Core.Controllers.BlogController})">
<summary>
构造函数
</summary>
<param name="blogArticleServices"></param>
<param name="logger"></param>
</member>
<member name="M:Blog.Core.Controllers.BlogController.Get(System.Int32,System.Int32,System.String,System.String)">
<summary>
@ -519,6 +519,13 @@
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TasksQzController.ExecuteJob(System.Int32)">
<summary>
立即执行任务
</summary>
<param name="jobId"></param>
<returns></returns>
</member>
<member name="T:Blog.Core.Controllers.TopicController">
<summary>
类别管理【无权限】

View File

@ -0,0 +1,86 @@
using Blog.Core.Model;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Blog.Core.Controllers
{
public class BaseApiCpntroller : Controller
{
[NonAction]
public MessageModel<T> Success<T>(T data, string msg = "成功")
{
return new MessageModel<T>()
{
success = true,
msg = msg,
response = data,
};
}
[NonAction]
public MessageModel Success(string msg = "成功")
{
return new MessageModel()
{
success = true,
msg = msg,
response = null,
};
}
[NonAction]
public MessageModel<string> Failed(string msg = "失败", int status = 500)
{
return new MessageModel<string>()
{
success = false,
status = status,
msg = msg,
response = null,
};
}
[NonAction]
public MessageModel<T> Failed<T>(string msg = "失败", int status = 500)
{
return new MessageModel<T>()
{
success = false,
status = status,
msg = msg,
response = default,
};
}
[NonAction]
public MessageModel<PageModel<T>> SuccessPage<T>(int page, int dataCount, List<T> data, int pageCount, string msg = "获取成功")
{
return new MessageModel<PageModel<T>>()
{
success = true,
msg = msg,
response = new PageModel<T>()
{
page = page,
dataCount = dataCount,
data = data,
pageCount = pageCount,
}
};
}
[NonAction]
public MessageModel<PageModel<T>> SuccessPage<T>(PageModel<T> pageModel, string msg = "获取成功")
{
return new MessageModel<PageModel<T>>()
{
success = true,
msg = msg,
response = new PageModel<T>()
{
page = pageModel.page,
dataCount = pageModel.dataCount,
data = pageModel.data,
pageCount = pageModel.pageCount,
}
};
}
}
}

View File

@ -22,7 +22,7 @@ namespace Blog.Core.Controllers
/// </summary>
[Produces("application/json")]
[Route("api/Blog")]
public class BlogController : ControllerBase
public class BlogController : BaseApiCpntroller
{
public IBlogArticleServices _blogArticleServices { get; set; }
private readonly ILogger<BlogController> _logger;
@ -30,9 +30,9 @@ namespace Blog.Core.Controllers
/// <summary>
/// 构造函数
/// </summary>
/// <param name="blogArticleServices"></param>
/// <param name="logger"></param>
public BlogController(IBlogArticleServices blogArticleServices, ILogger<BlogController> logger)
///
public BlogController(ILogger<BlogController> logger)
{
_logger = logger;
}
@ -56,8 +56,6 @@ namespace Blog.Core.Controllers
}
Expression<Func<BlogArticle, bool>> whereExpression = a => (a.bcategory == bcategory && a.IsDeleted == false) && ((a.btitle != null && a.btitle.Contains(key)) || (a.bcontent != null && a.bcontent.Contains(key)));
var testId = await _blogArticleServices.GetBlogDetails(1);
var pageModelBlog = await _blogArticleServices.QueryPage(whereExpression, page, intPageSize, " bID desc ");
@ -77,18 +75,7 @@ namespace Blog.Core.Controllers
}
}
return new MessageModel<PageModel<BlogArticle>>()
{
success = true,
msg = "获取成功",
response = new PageModel<BlogArticle>()
{
page = page,
dataCount = pageModelBlog.dataCount,
data = pageModelBlog.data,
pageCount = pageModelBlog.pageCount,
}
};
return SuccessPage(pageModelBlog);
}
@ -102,12 +89,7 @@ namespace Blog.Core.Controllers
[Authorize]
public async Task<MessageModel<BlogViewModels>> Get(int id)
{
return new MessageModel<BlogViewModels>()
{
msg = "获取成功",
success = true,
response = await _blogArticleServices.GetBlogDetails(id)
};
return Success<BlogViewModels>(await _blogArticleServices.GetBlogDetails(id));
}
@ -121,12 +103,7 @@ namespace Blog.Core.Controllers
public async Task<MessageModel<BlogViewModels>> DetailNuxtNoPer(int id)
{
_logger.LogInformation("xxxxxxxxxxxxxxxxxxx");
return new MessageModel<BlogViewModels>()
{
msg = "获取成功",
success = true,
response = await _blogArticleServices.GetBlogDetails(id)
};
return Success<BlogViewModels>(await _blogArticleServices.GetBlogDetails(id));
}
[HttpGet]
@ -156,15 +133,9 @@ namespace Blog.Core.Controllers
if (types.IsNotEmptyOrNull())
{
var blogs = await _blogArticleServices.Query(d => d.bcategory != null && types.Contains(d.bcategory) && d.IsDeleted == false);
return new MessageModel<List<BlogArticle>>()
{
msg = "获取成功",
success = true,
response = blogs
};
return Success(blogs);
}
return new MessageModel<List<BlogArticle>>() { };
return Success(new List<BlogArticle>() { });
}
[HttpGet]
@ -173,15 +144,9 @@ namespace Blog.Core.Controllers
{
if (id > 0)
{
return new MessageModel<BlogArticle>()
{
msg = "获取成功",
success = true,
response = await _blogArticleServices.QueryById(id)
};
return Success(await _blogArticleServices.QueryById(id));
}
return new MessageModel<BlogArticle>() { };
return Success(new BlogArticle());
}
/// <summary>
@ -198,12 +163,7 @@ namespace Blog.Core.Controllers
[CustomRoute(ApiVersions.V2, "Blogtest")]
public MessageModel<string> V2_Blogtest()
{
return new MessageModel<string>()
{
msg = "获取成功",
success = true,
response = "我是第二版的博客信息"
};
return Success<string>("我是第二版的博客信息");
}
/// <summary>
@ -216,22 +176,12 @@ namespace Blog.Core.Controllers
[Authorize]
public async Task<MessageModel<string>> Post([FromBody] BlogArticle blogArticle)
{
var data = new MessageModel<string>();
blogArticle.bCreateTime = DateTime.Now;
blogArticle.bUpdateTime = DateTime.Now;
blogArticle.IsDeleted = false;
blogArticle.bcategory = "技术博文";
var id = (await _blogArticleServices.Add(blogArticle));
data.success = id > 0;
if (data.success)
{
data.response = id.ObjToString();
data.msg = "添加成功";
}
return data;
return id > 0 ? Success<string>(id.ObjToString()) : Failed("添加失败");
}
@ -245,21 +195,11 @@ namespace Blog.Core.Controllers
[Authorize(Permissions.Name)]
public async Task<MessageModel<string>> AddForMVP([FromBody] BlogArticle blogArticle)
{
var data = new MessageModel<string>();
blogArticle.bCreateTime = DateTime.Now;
blogArticle.bUpdateTime = DateTime.Now;
blogArticle.IsDeleted = false;
var id = (await _blogArticleServices.Add(blogArticle));
data.success = id > 0;
if (data.success)
{
data.response = id.ObjToString();
data.msg = "添加成功";
}
return data;
return id > 0 ? Success<string>(id.ObjToString()) : Failed("添加失败");
}
/// <summary>
/// 更新博客信息
@ -272,7 +212,6 @@ namespace Blog.Core.Controllers
[Authorize(Permissions.Name)]
public async Task<MessageModel<string>> Put([FromBody] BlogArticle BlogArticle)
{
var data = new MessageModel<string>();
if (BlogArticle != null && BlogArticle.bID > 0)
{
var model = await _blogArticleServices.QueryById(BlogArticle.bID);
@ -285,17 +224,11 @@ namespace Blog.Core.Controllers
model.bcontent = BlogArticle.bcontent;
model.btraffic = BlogArticle.btraffic;
data.success = await _blogArticleServices.Update(model);
if (data.success)
{
data.msg = "更新成功";
data.response = BlogArticle?.bID.ObjToString();
}
if (await _blogArticleServices.Update(model))
Success<string>(BlogArticle?.bID.ObjToString());
}
}
return data;
return Failed("更新失败");
}
@ -310,20 +243,13 @@ namespace Blog.Core.Controllers
[Route("Delete")]
public async Task<MessageModel<string>> Delete(int id)
{
var data = new MessageModel<string>();
if (id > 0)
{
var blogArticle = await _blogArticleServices.QueryById(id);
blogArticle.IsDeleted = true;
data.success = await _blogArticleServices.Update(blogArticle);
if (data.success)
{
data.msg = "删除成功";
data.response = blogArticle?.bID.ObjToString();
}
return await _blogArticleServices.Update(blogArticle) ? Success<string>(blogArticle?.bID.ObjToString(), "删除成功") : Failed("删除失败");
}
return data;
return Failed("入参无效");
}
/// <summary>
/// apache jemeter 压力测试
@ -334,12 +260,7 @@ namespace Blog.Core.Controllers
[Route("ApacheTestUpdate")]
public async Task<MessageModel<bool>> ApacheTestUpdate()
{
return new MessageModel<bool>()
{
success = true,
msg = "更新成功",
response = await _blogArticleServices.Update(new { bsubmitter = $"laozhang{DateTime.Now.Millisecond}", bID = 1 })
};
return Success(await _blogArticleServices.Update(new { bsubmitter = $"laozhang{DateTime.Now.Millisecond}", bID = 1 }), "更新成功");
}
}
}

View File

@ -23,7 +23,7 @@ namespace Blog.Core.Controllers
[Produces("application/json")]
[Route("api/Login")]
[AllowAnonymous]
public class LoginController : Controller
public class LoginController : BaseApiCpntroller
{
readonly ISysUserInfoServices _sysUserInfoServices;
readonly IUserRoleServices _userRoleServices;
@ -146,13 +146,7 @@ namespace Blog.Core.Controllers
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
{
return new MessageModel<TokenInfoViewModel>()
{
success = false,
msg = "用户名或密码不能为空",
};
}
return Failed<TokenInfoViewModel>("用户名或密码不能为空");
pass = MD5Helper.MD5Encrypt32(pass);
@ -186,20 +180,11 @@ namespace Blog.Core.Controllers
}
var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
return new MessageModel<TokenInfoViewModel>()
{
success = true,
msg = "获取成功",
response = token
};
return Success(token, "获取成功");
}
else
{
return new MessageModel<TokenInfoViewModel>()
{
success = false,
msg = "认证失败",
};
return Failed<TokenInfoViewModel>("认证失败");
}
}
@ -215,13 +200,7 @@ namespace Blog.Core.Controllers
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(token))
{
return new MessageModel<TokenInfoViewModel>()
{
success = false,
msg = "token无效请重新登录",
};
}
return Failed<TokenInfoViewModel>("token无效请重新登录");
var tokenModel = JwtHelper.SerializeJwt(token);
if (tokenModel != null && tokenModel.Uid > 0)
{
@ -241,20 +220,10 @@ namespace Blog.Core.Controllers
identity.AddClaims(claims);
var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
return new MessageModel<TokenInfoViewModel>()
{
success = true,
msg = "获取成功",
response = refreshToken
};
return Success(refreshToken, "获取成功");
}
}
return new MessageModel<TokenInfoViewModel>()
{
success = false,
msg = "认证失败!",
};
return Failed<TokenInfoViewModel>("认证失败!");
}
/// <summary>

View File

@ -26,7 +26,7 @@ namespace Blog.Core.Controllers
[Route("api/[Controller]/[action]")]
[ApiController]
[AllowAnonymous]
public class MonitorController : Controller
public class MonitorController : BaseApiCpntroller
{
private readonly IHubContext<ChatHub> _hubContext;
private readonly IWebHostEnvironment _env;
@ -48,21 +48,16 @@ namespace Blog.Core.Controllers
[HttpGet]
public MessageModel<ServerViewModel> Server()
{
return new MessageModel<ServerViewModel>()
return Success(new ServerViewModel()
{
msg = "获取成功",
success = true,
response = new ServerViewModel()
{
EnvironmentName = _env.EnvironmentName,
OSArchitecture = RuntimeInformation.OSArchitecture.ObjToString(),
ContentRootPath = _env.ContentRootPath,
WebRootPath = _env.WebRootPath,
FrameworkDescription = RuntimeInformation.FrameworkDescription,
MemoryFootprint = (Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB",
WorkingTime = DateHelper.TimeSubTract(DateTime.Now, Process.GetCurrentProcess().StartTime)
}
};
EnvironmentName = _env.EnvironmentName,
OSArchitecture = RuntimeInformation.OSArchitecture.ObjToString(),
ContentRootPath = _env.ContentRootPath,
WebRootPath = _env.WebRootPath,
FrameworkDescription = RuntimeInformation.FrameworkDescription,
MemoryFootprint = (Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB",
WorkingTime = DateHelper.TimeSubTract(DateTime.Now, Process.GetCurrentProcess().StartTime)
});
}
@ -77,12 +72,7 @@ namespace Blog.Core.Controllers
_hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData()).Wait();
return new MessageModel<List<LogInfo>>()
{
msg = "获取成功",
success = true,
response = null
};
return Success<List<LogInfo>>(null);
}
@ -90,12 +80,7 @@ namespace Blog.Core.Controllers
[HttpGet]
public MessageModel<RequestApiWeekView> GetRequestApiinfoByWeek()
{
return new MessageModel<RequestApiWeekView>()
{
msg = "获取成功",
success = true,
response = LogLock.RequestApiinfoByWeek()
};
return Success(LogLock.RequestApiinfoByWeek());
}
[HttpGet]
@ -121,7 +106,7 @@ namespace Blog.Core.Controllers
}
[HttpGet]
public MessageModel<WelcomeInitData> GetActiveUsers([FromServices]IWebHostEnvironment environment)
public MessageModel<WelcomeInitData> GetActiveUsers([FromServices] IWebHostEnvironment environment)
{
var accessLogsToday = JsonConvert.DeserializeObject<List<UserAccessModel>>("[" + LogLock.ReadLog(
Path.Combine(environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.PrefixLatest

View File

@ -501,6 +501,28 @@ namespace Blog.Core.Controllers
var implementTypes = types.Where(x => x.IsClass).Select(item => new QuartzReflectionViewModel { nameSpace = item.Namespace, nameClass = item.Name, remark = "" }).ToList();
return MessageModel<List<QuartzReflectionViewModel>>.Success("获取成功", implementTypes);
}
/// <summary>
/// 立即执行任务
/// </summary>
/// <param name="jobId"></param>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<string>> ExecuteJob(int jobId)
{
var data = new MessageModel<string>();
var model = await _tasksQzServices.QueryById(jobId);
if (model != null)
{
return await _schedulerCenter.ExecuteJobAsync(model);
}
else
{
data.msg = "任务不存在";
}
return data;
}
}
}

View File

@ -50,7 +50,13 @@
"Enabled": false
},
"SqlAOP": {
"Enabled": false
"Enabled": true,
"OutToLogFile": {
"Enabled": false
},
"OutToConsole": {
"Enabled": true
}
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //

View File

@ -16,6 +16,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="RestSharp" Version="106.11.7" />
<PackageReference Include="RSAExtensions" Version="1.0.3" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1" />
<PackageReference Include="StackExchange.Redis" Version="2.1.58" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.8.0" />

View File

@ -4,7 +4,7 @@ namespace Blog.Core.Common.Helper
{
public static class ConsoleHelper
{
static void WriteColorLine(string str, ConsoleColor color)
public static void WriteColorLine(string str, ConsoleColor color)
{
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = color;

View File

@ -83,6 +83,24 @@ namespace Blog.Core.Common.Helper
return Path.Combine(folderPath, $@"{prefix}_{DateTime.Now.DateToTimeStamp()}.log");
}
public static string GetAvailableFileNameWithPrefixOrderSize(string _contentRoot, string prefix, int size = 1 * 1024 * 1024, string ext = ".log")
{
var folderPath = Path.Combine(_contentRoot, "Log");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
var allFiles = new DirectoryInfo(folderPath);
var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList();
if (selectFiles.Count > 0)
{
return selectFiles.FirstOrDefault().Name.Replace(".log","");
}
return $@"{prefix}_{DateTime.Now.DateToTimeStamp()}";
}
#endregion
#region

View File

@ -50,7 +50,7 @@ namespace Blog.Core.Common.Helper
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
if (encoding == null || encoding.Length < 1)
if (encoding.Length < 1)
{
encoding = "UTF-8"; //默认编码
}
@ -75,7 +75,7 @@ namespace Blog.Core.Common.Helper
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
if (encoding == null || encoding.Length < 1)
if (encoding.Length < 1)
{
encoding = "UTF-8"; //默认编码
}

View File

@ -100,5 +100,399 @@ namespace Blog.Core.Common.Helper
return st.ToString();
}
private static bool IsJsonStart(ref string json)
{
if (!string.IsNullOrEmpty(json))
{
json = json.Trim('\r', '\n', ' ');
if (json.Length > 1)
{
char s = json[0];
char e = json[json.Length - 1];
return (s == '{' && e == '}') || (s == '[' && e == ']');
}
}
return false;
}
public static bool IsJson(string json)
{
int errIndex;
return IsJson(json, out errIndex);
}
public static bool IsJson(string json, out int errIndex)
{
errIndex = 0;
if (IsJsonStart(ref json))
{
CharState cs = new CharState();
char c;
for (int i = 0; i < json.Length; i++)
{
c = json[i];
if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
{
string item = json.Substring(i);
int err;
int length = GetValueLength(item, true, out err);
cs.childrenStart = false;
if (err > 0)
{
errIndex = i + err;
return false;
}
i = i + length - 1;
}
if (cs.isError)
{
errIndex = i;
return false;
}
}
return !cs.arrayStart && !cs.jsonStart;
}
return false;
}
/// <summary>
/// 获取值的长度当Json值嵌套以"{"或"["开头时)
/// </summary>
private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
{
errIndex = 0;
int len = 0;
if (!string.IsNullOrEmpty(json))
{
CharState cs = new CharState();
char c;
for (int i = 0; i < json.Length; i++)
{
c = json[i];
if (!SetCharState(c, ref cs))//设置关键符号状态。
{
if (!cs.jsonStart && !cs.arrayStart)//json结束又不是数组则退出。
{
break;
}
}
else if (cs.childrenStart)//正常字符,值状态下。
{
int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
cs.childrenStart = false;
cs.valueStart = 0;
//cs.state = 0;
i = i + length - 1;
}
if (breakOnErr && cs.isError)
{
errIndex = i;
return i;
}
if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
{
len = i + 1;//长度比索引+1
break;
}
}
}
return len;
}
/// <summary>
/// 设置字符状态(返回true则为关键词返回false则当为普通字符处理
/// </summary>
private static bool SetCharState(char c, ref CharState cs)
{
cs.CheckIsError(c);
switch (c)
{
case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
#region
if (cs.keyStart <= 0 && cs.valueStart <= 0)
{
cs.keyStart = 0;
cs.valueStart = 0;
if (cs.jsonStart && cs.state == 1)
{
cs.childrenStart = true;
}
else
{
cs.state = 0;
}
cs.jsonStart = true;//开始。
return true;
}
#endregion
break;
case '}':
#region
if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
{
cs.jsonStart = false;//正常结束。
cs.state = 0;
cs.keyStart = 0;
cs.valueStart = 0;
cs.setDicValue = true;
return true;
}
// cs.isError = !cs.jsonStart && cs.state == 0;
#endregion
break;
case '[':
#region
if (!cs.jsonStart)
{
cs.arrayStart = true;
return true;
}
else if (cs.jsonStart && cs.state == 1)
{
cs.childrenStart = true;
return true;
}
#endregion
break;
case ']':
#region
if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
{
cs.keyStart = 0;
cs.valueStart = 0;
cs.arrayStart = false;
return true;
}
#endregion
break;
case '"':
case '\'':
#region
if (cs.jsonStart || cs.arrayStart)
{
if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
{
if (cs.keyStart <= 0)
{
cs.keyStart = (c == '"' ? 3 : 2);
return true;
}
else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"'))
{
if (!cs.escapeChar)
{
cs.keyStart = -1;
return true;
}
else
{
cs.escapeChar = false;
}
}
}
else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
{
if (cs.valueStart <= 0)
{
cs.valueStart = (c == '"' ? 3 : 2);
return true;
}
else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"'))
{
if (!cs.escapeChar)
{
cs.valueStart = -1;
return true;
}
else
{
cs.escapeChar = false;
}
}
}
}
#endregion
break;
case ':':
#region
if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
{
if (cs.keyStart == 1)
{
cs.keyStart = -1;
}
cs.state = 1;
return true;
}
// cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
#endregion
break;
case ',':
#region //["aa",{aa:12,}]
if (cs.jsonStart)
{
if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
{
cs.state = 0;
cs.keyStart = 0;
cs.valueStart = 0;
//if (cs.valueStart == 1)
//{
// cs.valueStart = 0;
//}
cs.setDicValue = true;
return true;
}
}
else if (cs.arrayStart && cs.keyStart <= 2)
{
cs.keyStart = 0;
//if (cs.keyStart == 1)
//{
// cs.keyStart = -1;
//}
return true;
}
#endregion
break;
case ' ':
case '\r':
case '\n'://[ "a",\r\n{} ]
case '\0':
case '\t':
if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
{
return true;//跳过空格。
}
break;
default: //值开头。。
if (c == '\\') //转义符号
{
if (cs.escapeChar)
{
cs.escapeChar = false;
}
else
{
cs.escapeChar = true;
return true;
}
}
else
{
cs.escapeChar = false;
}
if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
{
if (cs.keyStart <= 0 && cs.state == 0)
{
cs.keyStart = 1;//无引号的
}
else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
{
cs.valueStart = 1;//无引号的
}
}
break;
}
return false;
}
}
/// <summary>
/// 字符状态
/// </summary>
public class CharState
{
internal bool jsonStart = false;//以 "{"开始了...
internal bool setDicValue = false;// 可以设置字典值了。
internal bool escapeChar = false;//以"\"转义符号开始了
/// <summary>
/// 数组开始【仅第一开头才算】值嵌套的以【childrenStart】来标识。
/// </summary>
internal bool arrayStart = false;//以"[" 符号开始了
internal bool childrenStart = false;//子级嵌套开始了。
/// <summary>
/// 【0 初始状态,或 遇到“,”逗号】【1 遇到“:”冒号】
/// </summary>
internal int state = 0;
/// <summary>
/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
/// </summary>
internal int keyStart = 0;
/// <summary>
/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
/// </summary>
internal int valueStart = 0;
internal bool isError = false;//是否语法错误。
internal void CheckIsError(char c)//只当成一级处理因为GetLength会递归到每一个子项处理
{
if (keyStart > 1 || valueStart > 1)
{
return;
}
//示例 ["aa",{"bbbb":123,"fff","ddd"}]
switch (c)
{
case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
break;
case '}':
isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 或者 提前结束{"aa"}。正常的有{}
break;
case '[':
isError = arrayStart && state == 0;//重复开始错误
break;
case ']':
isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束
break;
case '"':
case '\'':
isError = !(jsonStart || arrayStart); //json 或数组开始。
if (!isError)
{
//重复开始 [""",{"" "}]
isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);
}
if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
{
isError = true;
}
break;
case ':':
isError = !jsonStart || state == 1;//重复出现。
break;
case ',':
isError = !(jsonStart || arrayStart); //json 或数组开始。
if (!isError)
{
if (jsonStart)
{
isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
}
else if (arrayStart)//["aa,] [,] [{},{}]
{
isError = keyStart == 0 && !setDicValue;
}
}
break;
case ' ':
case '\r':
case '\n'://[ "a",\r\n{} ]
case '\0':
case '\t':
break;
default: //值开头。。
isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
break;
}
//if (isError)
//{
//}
}
}
}

View File

@ -102,9 +102,9 @@ namespace Blog.Core.Common.Helper
/// <param name="resourceStr"></param>
/// <param name="length"></param>
/// <returns></returns>
public static string GetCusLine(string resourceStr,int length) {
public static string GetCusLine(string resourceStr, int length) {
string[] arrStr = resourceStr.Split("\r\n");
return string.Join("", (from q in arrStr select q).Skip(arrStr.Length - length+1).Take(length).ToArray());
return string.Join("", (from q in arrStr select q).Skip(arrStr.Length - length + 1).Take(length).ToArray());
}
}

View File

@ -5,7 +5,7 @@
/// <summary>
/// UrlEncode编码
/// </summary>
/// <param name="data">url</param>
/// <param name="url">url</param>
/// <returns></returns>
public static string UrlEncode(string url) {
return System.Web.HttpUtility.UrlEncode(url, System.Text.Encoding.UTF8);

View File

@ -15,7 +15,7 @@ namespace Blog.Core
{
int reval = 0;
if (thisValue == null) return 0;
if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
{
return reval;
}

View File

@ -318,11 +318,17 @@ namespace Blog.Core.Common.LogHelper
jsonBuilder.Append(item.count);
jsonBuilder.Append("\",");
}
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
if (apiweeksCurrentWeek.Count > 0)
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
jsonBuilder.Append("},");
}
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
if (weeks.Count > 0)
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
jsonBuilder.Append("]");
//columns.AddRange(apiWeeks.OrderByDescending(d => d.count).Take(8).Select(d => d.url).ToList());

View File

@ -1,5 +1,7 @@
using Serilog;
using Blog.Core.Common.Helper;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using System;
using System.IO;
@ -13,27 +15,51 @@ namespace Blog.Core.Common.LogHelper
/// <param name="filename"></param>
/// <param name="message"></param>
/// <param name="info"></param>
public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true)
public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
.WriteTo.File(Path.Combine($"log/Serilog/", $"{filename}.log"), rollingInterval: RollingInterval.Infinite, outputTemplate: "{Message}{NewLine}{Exception}")
.WriteTo.File(Path.Combine("Log", defaultFolder, $"{filename}.log"),
rollingInterval: RollingInterval.Infinite,
outputTemplate: "{Message}{NewLine}{Exception}")
// 将日志托送到远程ES
// docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d --name ES01 elasticsearch:7.2.0
//.Enrich.FromLogContext()
//.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://x.xxx.xx.xx:9200/"))
//{
// AutoRegisterTemplate = true,
//})
.CreateLogger();
var now = DateTime.Now;
string logContent = String.Join("\r\n", dataParas);
if (IsHeader)
var isJsonFormat = true;
if (isJudgeJsonFormat)
{
logContent = (
"--------------------------------\r\n" +
DateTime.Now + "|\r\n" +
String.Join("\r\n", dataParas) + "\r\n"
);
var judCont = logContent.Substring(0, logContent.LastIndexOf(","));
isJsonFormat = JsonHelper.IsJson(judCont);
}
Log.Information(logContent);
if (isJsonFormat)
{
if (IsHeader)
{
logContent = (
"--------------------------------\r\n" +
DateTime.Now + "|\r\n" +
String.Join("\r\n", dataParas) + "\r\n"
);
}
Log.Information(logContent);
}
else
{
Console.WriteLine("【JSON格式异常】"+logContent + now.ObjToString());
}
Log.CloseAndFlush();
}
/// <summary>
@ -53,4 +79,4 @@ namespace Blog.Core.Common.LogHelper
Log.CloseAndFlush();
}
}
}
}

View File

@ -44,7 +44,7 @@ namespace Blog.Core.AOP
/// <returns></returns>
protected static string GetArgumentValue(object arg)
{
if (arg is DateTime || arg is DateTime?)
if (arg is DateTime)
return ((DateTime)arg).ToString("yyyyMMddHHmmss");
if (!arg.IsNotEmptyOrNull())
@ -108,7 +108,7 @@ namespace Blog.Core.AOP
case ExpressionType.GreaterThanOrEqual:
return ">=";
default:
throw new Exception(string.Format("不支持{0}此种运算符查找!" + expressiontype));
throw new Exception($"不支持{expressiontype}此种运算符查找!");
}
}
@ -135,7 +135,7 @@ namespace Blog.Core.AOP
case "LongCount":
return Len(MethodCall, value, expressiontype.Value);
default:
throw new Exception(string.Format("不支持{0}方法的查找!", MethodName));
throw new Exception($"不支持{MethodName}方法的查找!");
}
}
@ -155,7 +155,7 @@ namespace Blog.Core.AOP
string Name = Argument2.Member.Name;
string Operator = Convert.ToBoolean(isTrue) ? "in" : " not in";
string CompName = string.Join(",", SetInPara);
string Result = string.Format("{0} {1} ({2})", Name, Operator, CompName);
string Result = $"{Name} {Operator} ({CompName})";
return Result;
}
private static string Like(MethodCallExpression expression)
@ -165,9 +165,9 @@ namespace Blog.Core.AOP
LambdaExpression lambda = Expression.Lambda(Temp);
Delegate fn = lambda.Compile();
var tempValue = Expression.Constant(fn.DynamicInvoke(null), Temp.Type);
string Value = string.Format("%{0}%", tempValue);
string Value = $"%{tempValue}%";
string Name = (expression.Object as MemberExpression).Member.Name;
string Result = string.Format("{0} like {1}", Name, Value);
string Result = $"{Name} like {Value}";
return Result;
}
@ -176,7 +176,7 @@ namespace Blog.Core.AOP
{
object Name = (expression.Arguments[0] as MemberExpression).Member.Name;
string Operator = GetOperator(expressiontype);
string Result = string.Format("len({0}){1}{2}", Name, Operator, value.ToString());
string Result = $"len({Name}){Operator}{value.ToString()}";
return Result;
}

View File

@ -1,5 +1,7 @@
using Blog.Core.Common;
using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
@ -17,13 +19,17 @@ namespace Blog.Core.Middlewares
///
/// </summary>
private readonly RequestDelegate _next;
private readonly IWebHostEnvironment _environment;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(IPLogMildd));
/// <summary>
///
/// </summary>
/// <param name="next"></param>
public IPLogMildd(RequestDelegate next)
public IPLogMildd(RequestDelegate next, IWebHostEnvironment environment)
{
_next = next;
_environment = environment;
}
public async Task InvokeAsync(HttpContext context)
@ -51,13 +57,25 @@ namespace Blog.Core.Middlewares
if (!string.IsNullOrEmpty(requestInfo))
{
// 自定义log输出
Parallel.For(0, 1, e =>
{
LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
});
//Parallel.For(0, 1, e =>
//{
// LogLock.OutSql2Log("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
//});
try
{
var testLogMatchRequestInfo = JsonConvert.DeserializeObject<RequestInfo>(requestInfo);
if (testLogMatchRequestInfo != null)
{
var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RequestIpInfoLog");
SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false, "", true);
}
}
catch (Exception e)
{
log.Error(requestInfo + "\r\n" + e.GetBaseException().ToString());
}
// 这种方案也行用的是Serilog
//SerilogServer.WriteLog("RequestIpInfoLog", new string[] { requestInfo + "," }, false);
request.Body.Position = 0;
}

View File

@ -1,6 +1,8 @@
using Blog.Core.Common;
using Blog.Core.Common.Helper;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
@ -25,17 +27,19 @@ namespace Blog.Core.Middlewares
private readonly RequestDelegate _next;
private readonly IUser _user;
private readonly ILogger<RecordAccessLogsMildd> _logger;
private readonly IWebHostEnvironment _environment;
private Stopwatch _stopwatch;
/// <summary>
///
/// </summary>
/// <param name="next"></param>
public RecordAccessLogsMildd(RequestDelegate next, IUser user, ILogger<RecordAccessLogsMildd> logger)
public RecordAccessLogsMildd(RequestDelegate next, IUser user, ILogger<RecordAccessLogsMildd> logger, IWebHostEnvironment environment)
{
_next = next;
_user = user;
_logger = logger;
_environment = environment;
_stopwatch = new Stopwatch();
}
@ -102,10 +106,14 @@ namespace Blog.Core.Middlewares
// 自定义log输出
var requestInfo = JsonConvert.SerializeObject(userAccessModel);
Parallel.For(0, 1, e =>
{
LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false);
});
//Parallel.For(0, 1, e =>
//{
// LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false);
//});
var logFileName = FileHelper.GetAvailableFileNameWithPrefixOrderSize(_environment.ContentRootPath, "RecordAccessLogs");
SerilogServer.WriteLog(logFileName, new string[] { requestInfo + "," }, false);
return Task.CompletedTask;
});

View File

@ -91,11 +91,12 @@ namespace Blog.Core.Middlewares
if (!string.IsNullOrEmpty(content))
{
Parallel.For(0, 1, e =>
{
LogLock.OutSql2Log("RequestResponseLog", new string[] { "Request Data:", content });
//Parallel.For(0, 1, e =>
//{
// LogLock.OutSql2Log("RequestResponseLog", new string[] { "Request Data:", content });
});
//});
SerilogServer.WriteLog("RequestResponseLog", new string[] { "Request Data:", content });
request.Body.Position = 0;
}
@ -112,11 +113,12 @@ namespace Blog.Core.Middlewares
if (!string.IsNullOrEmpty(ResponseBody))
{
Parallel.For(0, 1, e =>
{
LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
//Parallel.For(0, 1, e =>
//{
// LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
});
//});
SerilogServer.WriteLog("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
}
}
}

View File

@ -154,7 +154,6 @@ namespace Blog.Core.Extensions
/// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="redisKey"></param>
/// <param name="db"></param>
/// <returns></returns>

View File

@ -69,6 +69,16 @@ namespace Blog.Core.Extensions
ConsoleHelper.WriteSuccessLine($"Service Log AOP: True");
}
// 开启的中间件日志
var requestResponseLogOpen = Appsettings.app(new string[] { "Middleware", "RequestResponseLog", "Enabled" }).ObjToBool();
var ipLogOpen = Appsettings.app(new string[] { "Middleware", "IPLog", "Enabled" }).ObjToBool();
var recordAccessLogsOpen = Appsettings.app(new string[] { "Middleware", "RecordAccessLogs", "Enabled" }).ObjToBool();
ConsoleHelper.WriteSuccessLine($"OPEN Log: " +
(requestResponseLogOpen ? "RequestResponseLog √," : "") +
(ipLogOpen ? "IPLog √," : "") +
(recordAccessLogsOpen ? "RecordAccessLogs √," : "")
);
// 事务AOP
if (!Appsettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
@ -80,13 +90,23 @@ namespace Blog.Core.Extensions
}
// 数据库Sql执行AOP
if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToLogFile", "Enabled" }).ObjToBool())
{
Console.WriteLine($"DB Sql AOP: False");
Console.WriteLine($"DB Sql AOP To LogFile: False");
}
else
{
ConsoleHelper.WriteSuccessLine($"DB Sql AOP: True");
ConsoleHelper.WriteSuccessLine($"DB Sql AOP To LogFile: True");
}
// Sql执行日志输出到控制台
if (!Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToConsole", "Enabled" }).ObjToBool())
{
Console.WriteLine($"DB Sql AOP To Console: False");
}
else
{
ConsoleHelper.WriteSuccessLine($"DB Sql AOP To Console: True");
}
// SingnalR发送数据
@ -118,7 +138,7 @@ namespace Blog.Core.Extensions
{
ConsoleHelper.WriteSuccessLine($"MiniProfiler: True");
}
// CORS跨域
if (!Appsettings.app("Startup", "Cors", "EnableAllIPs").ObjToBool())
{

View File

@ -1,5 +1,6 @@
using Blog.Core.Common;
using Blog.Core.Common.DB;
using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
@ -54,14 +55,21 @@ namespace Blog.Core.Extensions
{
if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
{
Parallel.For(0, 1, e =>
if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToLogFile", "Enabled" }).ObjToBool())
{
MiniProfiler.Current.CustomTiming("SQL", GetParas(p) + "【SQL语句】" + sql);
LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】" + sql });
Parallel.For(0, 1, e =>
{
MiniProfiler.Current.CustomTiming("SQL", GetParas(p) + "【SQL语句】" + sql);
LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】" + sql });
});
});
}
if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "OutToConsole", "Enabled" }).ObjToBool())
{
ConsoleHelper.WriteColorLine(string.Join("\r\n", new string[] { "--------", "【SQL语句】" + GetWholeSql(p, sql) }), ConsoleColor.DarkCyan);
}
}
}
},
},
MoreSettings = new ConnMoreSettings()
{
@ -89,6 +97,16 @@ namespace Blog.Core.Extensions
});
}
private static string GetWholeSql(SugarParameter[] paramArr, string sql)
{
foreach (var param in paramArr)
{
sql.Replace(param.ParameterName, param.Value.ObjToString());
}
return sql;
}
private static string GetParas(SugarParameter[] pars)
{
string key = "【SQL参数】";

View File

@ -75,4 +75,24 @@
return new MessageModel<T>() { msg = msg, response = response, success = success };
}
}
public class MessageModel
{
/// <summary>
/// 状态码
/// </summary>
public int status { get; set; } = 200;
/// <summary>
/// 操作是否成功
/// </summary>
public bool success { get; set; } = false;
/// <summary>
/// 返回信息
/// </summary>
public string msg { get; set; } = "";
/// <summary>
/// 返回数据集合
/// </summary>
public object response { get; set; }
}
}

View File

@ -403,7 +403,6 @@ namespace Blog.Core.Repository.Base
/// <param name="whereExpression">条件表达式</param>
/// <param name="intPageIndex">页码下标0</param>
/// <param name="intPageSize">页大小</param>
/// <param name="intTotalCount">数据总量</param>
/// <param name="strOrderByFileds">排序字段如name asc,age desc</param>
/// <returns>数据列表</returns>
public async Task<List<TEntity>> Query(
@ -423,7 +422,6 @@ namespace Blog.Core.Repository.Base
/// <param name="strWhere">条件</param>
/// <param name="intPageIndex">页码下标0</param>
/// <param name="intPageSize">页大小</param>
/// <param name="intTotalCount">数据总量</param>
/// <param name="strOrderByFileds">排序字段如name asc,age desc</param>
/// <returns>数据列表</returns>
public async Task<List<TEntity>> Query(

View File

@ -12,8 +12,7 @@ namespace Blog.Core.Repository.MongoRepository
public MongoDbContext()
{
var client = new MongoClient(Appsettings.app(new string[] { "Mongo", "ConnectionString" }));
if (client != null)
_database = client.GetDatabase(Appsettings.app(new string[] { "Mongo", "Database" }));
_database = client.GetDatabase(Appsettings.app(new string[] { "Mongo", "Database" }));
}
public IMongoDatabase Db

View File

@ -269,7 +269,6 @@ namespace Blog.Core.Services.BASE
/// <param name="whereExpression">条件表达式</param>
/// <param name="intPageIndex">页码下标0</param>
/// <param name="intPageSize">页大小</param>
/// <param name="intTotalCount">数据总量</param>
/// <param name="strOrderByFileds">排序字段如name asc,age desc</param>
/// <returns>数据列表</returns>
public async Task<List<TEntity>> Query(
@ -292,7 +291,6 @@ namespace Blog.Core.Services.BASE
/// <param name="strWhere">条件</param>
/// <param name="intPageIndex">页码下标0</param>
/// <param name="intPageSize">页大小</param>
/// <param name="intTotalCount">数据总量</param>
/// <param name="strOrderByFileds">排序字段如name asc,age desc</param>
/// <returns>数据列表</returns>
public async Task<List<TEntity>> Query(

View File

@ -63,7 +63,6 @@ namespace Blog.Core.Services
/// <summary>
/// 获取博客列表
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[Caching(AbsoluteExpiration = 10)]
public async Task<List<BlogArticle>> GetBlogs()

View File

@ -66,6 +66,13 @@ namespace Blog.Core.Tasks
/// <returns></returns>
string GetTriggerState(string key);
/// <summary>
/// 立即执行 一个任务
/// </summary>
/// <param name="tasksQz"></param>
/// <returns></returns>
Task<MessageModel<string>> ExecuteJobAsync(TasksQz tasksQz);
}
}

View File

@ -443,5 +443,49 @@ namespace Blog.Core.Tasks
}
#endregion
/// <summary>
/// 立即执行 一个任务
/// </summary>
/// <param name="tasksQz"></param>
/// <returns></returns>
public async Task<MessageModel<string>> ExecuteJobAsync(TasksQz tasksQz)
{
var result = new MessageModel<string>();
try
{
JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup);
//判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务
if (!await _scheduler.Result.CheckExists(jobKey))
{
//不存在 则 添加一个计划任务
await AddScheduleJobAsync(tasksQz);
//触发执行一次
await _scheduler.Result.TriggerJob(jobKey);
//停止任务
await StopScheduleJobAsync(tasksQz);
result.success = true;
result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
}
else
{
await _scheduler.Result.TriggerJob(jobKey);
result.success = true;
result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
}
}
catch (Exception ex)
{
result.msg = $"立即执行计划任务失败:【{ex.Message}】";
}
return result;
}
}
}

View File

@ -27,7 +27,7 @@ namespace Blog.Core.Tests
var container = dI_Test.DICollections();
blogArticleServices = container.Resolve<IBlogArticleServices>();
blogController = new BlogController(blogArticleServices, mockLogger.Object);
blogController = new BlogController(mockLogger.Object);
}
[Fact]

View File

@ -34,7 +34,13 @@
"Enabled": false
},
"SqlAOP": {
"Enabled": false
"Enabled": false,
"OutToLogFile": {
"Enabled": false
},
"OutToConsole": {
"Enabled": false
}
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //

View File

@ -1,50 +1,107 @@
[ENGLISH](https://github.com/anjoy8/Blog.Core/blob/master/README-en.md) | [中文版](https://github.com/anjoy8/Blog.Core/blob/master/README.md)
![Logo](https://github.com/anjoy8/Blog.Core/blob/master/Blog.Core/wwwroot/logocore.png)
Build your own front and rear end separation from scratch ". NET Core2.1 Api + Vue 2.0" framework, currently version 2.2, each version see branch.
It's just. Netcore back-end section, Front end section, see my other engineering vue
[![sdk](https://img.shields.io/badge/sdk-5.0.1-d.svg)](#) [![Build status](https://github.com/anjoy8/blog.core/workflows/.NET%20Core/badge.svg)](https://github.com/anjoy8/Blog.Core/actions) [![Build Status](https://dev.azure.com/laozhangisphi/anjoy8/_apis/build/status/anjoy8.Blog.Core?branchName=master)](https://dev.azure.com/laozhangisphi/anjoy8/_build?definitionId=1) [![codecov](https://codecov.io/gh/anjoy8/Blog.Core/branch/master/graph/badge.svg)](https://codecov.io/gh/anjoy8/Blog.Core) [![License MIT](https://img.shields.io/badge/license-Apache-blue.svg?style=flat-square)](https://github.com/anjoy8/Blog.Core/blob/master/LICENSE) [![star this repo](http://githubbadges.com/star.svg?user=anjoy8&repo=blog.core&style=flat)](https://github.com/boennemann/badges) [![fork this repo](http://githubbadges.com/fork.svg?user=anjoy8&repo=blog.core&style=flat)](https://github.com/boennemann/badges/fork) [![Cnblogs](https://img.shields.io/badge/博客园-老张的哲学-brightgreen.svg)](https://www.cnblogs.com/laozhang-is-phi/)
Https://github.com/anjoy8/Blog.Vue
# Give a star!⭐️
&nbsp;
&nbsp;
If you like this project or it helps you, please give star~ (hard Star)
*********************************************************
# Tips:
1. Blog.Core.FrameWork project is a simple implementation of generating files using T4 templates.
If there is an error, you can contact me,
QQ Group: 867095512
If you don't want to deal with this error, you can uninstall the project first without affecting the overall operation.
<div style="text-align: center;">
<a href="https://mvp.microsoft.com/zh-cn/PublicProfile/5003704?fullName=anson%20zhang" >
<img src="http://apk.neters.club/MVP_Logo_Horizontal_Preferred_Cyan300_CMYK_72ppi.png" alt="MVP" >
</a>
2. when the project is executed after downloading, the Redis server needs to be installed, installation and use of the description address:
https://www.cnblogs.com/laozhang-is-phi/p/9554210.html#autoid-5-0-0
<a href="https://dotnetfoundation.org/member/Profile" >
<img src="https://vueadmin.neters.club/images/1125120255netfoundation.png" alt=".netfoundation" width="220" >
</a>
</div>
3. the system new automated Generation database, and the ability to generate seed data, In the Progrm.cs in the Blog.core layer, cancel the Dbseed.seedasync (mycontext). Wait ();
The comment can be.
4. If you do not want to use Codefirst and seed data, you can use the database table structure SQL file to execute in the database,
Blog.Core is an enterprise-class back-to-back separation framework for.NET Core5.0 API + Vue 2.x + RBAC.
Website: http://apk.neters.club/.doc/
Has been used by several companies: [click to view list] (https://github.com/anjoy8/Blog.Core/issues/75)
Project single deployment, concurrent at 400~500, all normal (do not guarantee their own various error writing).
The effect is even better if the load is matched.
&nbsp;
### Features and Progress
Framework module:
- [x] adopts the form of 'repository + service + interface' to encapsulate the framework;
- [X] async/await development;
- [x] access to domestic database ORM component - SQLSUGAR, encapsulate database operation;
- [x] support free switching multiple database, MySql/used/Sqlite/Oracle/Postgresql/reach/NPC Jin Cang dreams;
- [x] realize project startup, automatically generate seed data ✨;
- [X] five types of logging, audit/exception/request response/service operation/SQL logging, etc.
- [x] Support for project transaction processing (use CAP if you want to distribute) ✨;
- [x] Design 4 types of AOP facets programming, including: logging, caching, auditing, transaction ✨;
- [x] Support T4 code template, automatically generate code for each layer;
- [x] or use DbFirst one key to create their own project four layer files (support multiple libraries);
- [x] encapsulation ` Blog. Core. Webapi. Template ` project Template, a key ✨ rebuild their projects;
- [x] with multiple front-end cases for reference and reference: blog.vue, blog.admin, nuxt.tbug, blog.mvp. Blazor ✨;
- [x] Uniform Integrated IdentityServer4 Authentication ✨;
Component module:
- [x] provides Redis for caching;
- [x] API file with Swagger;
- [x] Use Miniprofiler for interface performance analysis ✨;
- [x] uses Automapper to handle object mapping;
- [x] uses Autofac as a dependency injection container and provides batch service injection ✨;
- [x] supports CORS cross-domain;
- [x] encapsulates JWT custom policy authorization;
- [x] uses the Log4Net logging framework and integrates the native iLogger interface for logging;
- [x] using Signalr duplex communication ✨;
- [x] Added iprateLimiting for API current limiting;
- [X] Use Quartz.net for task scheduling (currently single machine multi-task, cluster scheduling is not currently supported);
- [x] Support for database 'read/write separation' and multi-library operations ✨;
- [x] Added Redis Message Queuing ✨;
- [x] new RabbitMQ message queue ✨;
- [x] New EventBus ✨;
- [x] Debugging - Unified Aggregate Payment;
- [ ] Plan - Data department authority;
- [ ] plan -es search;
Micro service module:
- [x] can cooperate with Docker to achieve containerization;
- [x] can cooperate with Jenkins to achieve CI/CD;
- [x] enables service discovery with Consul;
- [x] can cooperate with Ocelot to achieve gateway processing;
- [x] can cooperate with NGINX to achieve load balancing;
- [x] can cooperate with IDS4 certification center;
&nbsp;
## Give a star! ⭐
If you like this project or it helps you, please send it to STAR ~
If your project from the project, please explain a little bit down [https://github.com/anjoy8/Blog.Core/issues/75] (https://github.com/anjoy8/Blog.Core/issues/75), Open source is not easy ✨.
&nbsp;
## Official document 📕
Still in the process of sorting out, but the basic operations, including how to get started, configure data, connect to DB, and so on
[the official documentation] (http://apk.neters.club/.doc/)
[Official account important articles + video address](https://mvp.neters.club/)
&nbsp;
In the Wwwroot folder under the Blog.core project.
*********************************************************
### Modify Database connection string
1, in the Blog.Core.Repository layer under the Sugar folder under the BaseDBConfig.cs, configure their own strings
```
public static string connectionstring = File.exists (@ "D:my-filedbCountPsw1.txt")?
File.readalltext (@ "D:my-filedbCountPsw1.txt"). Trim (): "server=.;
Uid=sa;pwd=sa;database=blogdb ";
```
2, in the Blog.Core.FrameWork layer of the dbhelper.ttinclude, configure their own strings
```
public static readonly String connectionstring = File.exists (@ "D:my-filedbCountPsw2.txt")?
File.readalltext (@ "D:my-filedbCountPsw2.txt"). Trim (): "server=.;
Uid=sa;pwd=sa;database=blogdb ";
```
*****************************************************

View File

@ -2,7 +2,7 @@
# Blog.Core
[English](readme-en.md) | 简体中文
[English](README-en.md) | 简体中文
[![sdk](https://img.shields.io/badge/sdk-5.0.1-d.svg)](#) [![Build status](https://github.com/anjoy8/blog.core/workflows/.NET%20Core/badge.svg)](https://github.com/anjoy8/Blog.Core/actions) [![Build Status](https://dev.azure.com/laozhangisphi/anjoy8/_apis/build/status/anjoy8.Blog.Core?branchName=master)](https://dev.azure.com/laozhangisphi/anjoy8/_build?definitionId=1) [![codecov](https://codecov.io/gh/anjoy8/Blog.Core/branch/master/graph/badge.svg)](https://codecov.io/gh/anjoy8/Blog.Core) [![License MIT](https://img.shields.io/badge/license-Apache-blue.svg?style=flat-square)](https://github.com/anjoy8/Blog.Core/blob/master/LICENSE) [![star this repo](http://githubbadges.com/star.svg?user=anjoy8&repo=blog.core&style=flat)](https://github.com/boennemann/badges) [![fork this repo](http://githubbadges.com/fork.svg?user=anjoy8&repo=blog.core&style=flat)](https://github.com/boennemann/badges/fork) [![博客园](https://img.shields.io/badge/博客园-老张的哲学-brightgreen.svg)](https://www.cnblogs.com/laozhang-is-phi/)
@ -85,7 +85,19 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core5.0 Api + Vue 2.x
如果你喜欢这个项目或者它帮助你, 请给 Star~
如果你的项目中借鉴了本项目,请稍微说明下[https://github.com/anjoy8/Blog.Core/issues/75](https://github.com/anjoy8/Blog.Core/issues/75),开源不易✨。
## 贡献者们
Thanks goes to these wonderful people ([✨](https://github.com/anjoy8/Blog.Core/graphs/contributors)):
<!-- prettier-ignore-start -->
| [<img src="https://avatars3.githubusercontent.com/u/28941816?s=460&v=3" width="100px;"/><br /><sub> anjoy8</sub>](https://github.com/anjoy8) <br /> 💻📖 💡 | [<img src="https://avatars0.githubusercontent.com/u/36782822?s=460&v=3" width="100px;"/><br /><sub> hudingwen</sub>](https://github.com/hudingwen) <br /> 💻 👀 | [<img src="https://avatars0.githubusercontent.com/u/32299016?s=460&v=3" width="100px;"/><br /><sub>binyly </sub>](https://github.com/binyly) <br />💻 👀 📖 🤔 | [<img src="https://avatars0.githubusercontent.com/u/48714336?s=460&v=3" width="100px;"/><br /><sub>wuare </sub>](https://github.com/wuare) <br /> 💻 🐛 🤔 | [<img src="https://avatars3.githubusercontent.com/u/54385223?s=460&v=3" width="100px;"/><br /><sub>skang0401 </sub>](https://github.com/skang0401) <br /> 📖| [<img src="https://avatars1.githubusercontent.com/u/24422140?s=460&v=3" width="100px;"/><br /><sub>Jamnine</sub>](https://github.com/Jamnine) <br />💻 🌍|
| :---: | :---: | :---: | :---: | :---: | :---: |
|[<img src="https://avatars1.githubusercontent.com/u/19725014?s=460&v=3" width="118px;"/><br /><sub>aion1998 </sub>](https://github.com/aion1998) <br />🐛|[<img src="https://avatars1.githubusercontent.com/u/54570786?s=460&v=3" width="118px;"/><br /><sub>RLei123 </sub>](https://github.com/RLei123) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/33676184?s=460&v=3" width="118px;"/><br /><sub>cluyun </sub>](https://github.com/cluyun) <br />🌍|[<img src="https://avatars3.githubusercontent.com/u/33139361?s=460&v=3" width="118px;"/><br /><sub>blue20171027 </sub>](https://github.com/blue20171027) <br />💻|[<img src="https://avatars0.githubusercontent.com/u/15273487?s=460&v=3" width="118px;"/><br /><sub>anewboyz </sub>](https://github.com/anewboyz) <br />💻|[<img src="https://avatars3.githubusercontent.com/u/16607609?s=460&v=3" width="118px;"/><br /><sub>jxd728 </sub>](https://github.com/jxd728) <br />🌍|
|[<img src="https://avatars0.githubusercontent.com/u/25163291?s=460&v=3" width="118px;"/><br /><sub>wmchuang </sub>](https://github.com/wmchuang) <br />🌍|[<img src="https://avatars2.githubusercontent.com/u/23184470?s=400&v=3" width="118px;"/><br /><sub>liuzhenyulive </sub>](https://github.com/liuzhenyulive) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/34571008?s=400&v=3" width="118px;"/><br /><sub>JsonBy </sub>](https://github.com/JsonBy) <br />💻 💡 🤔|[<img src="https://avatars2.githubusercontent.com/u/34576675?s=400&v=3" width="118px;"/><br /><sub>hsxian </sub>](https://github.com/hsxian) <br />🌍|[<img src="https://avatars0.githubusercontent.com/u/58431215?s=400&v=4" width="118px;"/><br /><sub>cuno92 </sub>](https://github.com/cuno92) <br />📖|[<img src="https://avatars0.githubusercontent.com/u/22249987?s=400&v=3" width="118px;"/><br /><sub>317447880 </sub>](https://github.com/317447880) <br />💻|
<!-- prettier-ignore-end -->
This project follows the [all-contributors](https://github.com/anjoy8/Blog.Core/graphs/contributors) specification.
Contributions of any kind are welcome!
&nbsp;