/// <summary> /// 输出验证信息 /// </summary> /// <param name="errors"></param> /// <returns></returns> internal static (Dictionary <string, IEnumerable <string> > validationResults, string validateFaildMessage, ModelStateDictionary modelState) OutputValidationInfo(object errors) { ModelStateDictionary _modelState = null; Dictionary <string, IEnumerable <string> > validationResults = null; // 如果是模型验证字典类型 if (errors is ModelStateDictionary modelState) { _modelState = modelState; // 将验证错误信息转换成字典并序列化成 Json validationResults = modelState.ToDictionary(u => !JsonSerializerUtility.EnabledPascalPropertyNaming ? u.Key.ToTitlePascal() : u.Key , u => modelState[u.Key].Errors.Select(c => c.ErrorMessage)); } // 如果是 ValidationProblemDetails 特殊类型 else if (errors is ValidationProblemDetails validation) { validationResults = validation.Errors.ToDictionary(u => !JsonSerializerUtility.EnabledPascalPropertyNaming ? u.Key.ToTitlePascal() : u.Key , u => u.Value.AsEnumerable()); } // 其他类型 else { validationResults = new Dictionary <string, IEnumerable <string> > { { string.Empty, new[] { errors?.ToString() } } } }; // 序列化 var validateFaildMessage = JsonSerializerUtility.Serialize(validationResults); return(validationResults, validateFaildMessage, _modelState); } }
/// <summary> /// 设置验证失败结果 /// </summary> /// <param name="context">动作方法执行上下文</param> /// <param name="modelState">模型验证状态</param> /// <param name="actionDescriptor"></param> private static void SetValidateFailedResult(ActionExecutingContext context, ModelStateDictionary modelState, ControllerActionDescriptor actionDescriptor) { // 将验证错误信息转换成字典并序列化成 Json var validationResults = modelState.ToDictionary(u => u.Key, u => modelState[u.Key].Errors.Select(c => c.ErrorMessage)); var validateFaildMessage = JsonSerializerUtility.Serialize(validationResults); // 判断是否跳过规范化结果 if (UnifyResultContext.IsSkipUnifyHandler(actionDescriptor.MethodInfo, out var unifyResult)) { // 返回 400 错误 var result = new BadRequestObjectResult(modelState); // 设置返回的响应类型 result.ContentTypes.Add(MediaTypeNames.Application.Json); result.ContentTypes.Add(MediaTypeNames.Application.Xml); context.Result = result; } else { context.Result = unifyResult.OnValidateFailed(context, modelState, validationResults, validateFaildMessage); } // 打印验证失败信息 App.PrintToMiniProfiler(MiniProfilerCategory, "Failed", $"Validation Failed:\r\n{validateFaildMessage}", true); }
/// <summary> /// 处理输出状态码 /// </summary> /// <param name="context"></param> /// <param name="statusCode"></param> /// <returns></returns> public async Task OnResponseStatusCodes(HttpContext context, int statusCode) { switch (statusCode) { // 处理 401 状态码 case StatusCodes.Status401Unauthorized: await context.Response.WriteAsJsonAsync(new RESTfulResult <object> { StatusCode = StatusCodes.Status401Unauthorized, Successed = false, Data = null, Errors = "401 Unauthorized", Extras = UnifyResultContext.Take() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; // 处理 403 状态码 case StatusCodes.Status403Forbidden: await context.Response.WriteAsJsonAsync(new RESTfulResult <object> { StatusCode = StatusCodes.Status403Forbidden, Successed = false, Data = null, Errors = "403 Forbidden", Extras = UnifyResultContext.Take() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; default: break; } }
private static bool ReadAccessInfo(string accessInfoPath, out AccessInfo accessInfo) { accessInfo = AccessInfo.Empty; if (File.Exists(accessInfoPath) == false) { return(false); } accessInfo = (AccessInfo)JsonSerializerUtility.Read <AccessSerializationInfo>(accessInfoPath); return(true); }
/// <summary> /// 设置请求体 /// </summary> /// <param name="httpMethodAttribute"></param> /// <param name="methodParameters"></param> /// <param name="request"></param> private static void SetHttpRequestBody(HttpMethodAttribute httpMethodAttribute, Dictionary <string, ParameterValue> methodParameters, HttpRequestMessage request) { // 排除 GET/Head 请求 if (httpMethodAttribute.Method == HttpMethod.Get || httpMethodAttribute.Method == HttpMethod.Head) { return; } // 获取所有非基元类型,该类型当作 Body 参数 var bodyParameters = methodParameters.Where(u => u.Value.IsBodyParameter); if (bodyParameters.Any()) { // 获取 body 参数 var bodyArgs = bodyParameters.First().Value.Value; string body; // 处理 json 类型 if (httpMethodAttribute.ContentType.Contains("json")) { body = JsonSerializerUtility.Serialize(bodyArgs); } // 处理 xml 类型 else if (httpMethodAttribute.ContentType.Contains("xml")) { var xmlSerializer = new XmlSerializer(bodyArgs.GetType()); var buffer = new StringBuilder(); using var writer = new StringWriter(buffer); xmlSerializer.Serialize(writer, bodyArgs); body = buffer.ToString(); } // 其他类型 else { body = bodyArgs.ToString(); } if (!string.IsNullOrEmpty(body)) { var httpContent = new StringContent(body, Encoding.UTF8); // 设置内容类型 httpContent.Headers.ContentType = new MediaTypeHeaderValue(httpMethodAttribute.ContentType); request.Content = httpContent; // 打印请求地址 App.PrintToMiniProfiler(MiniProfilerCategory, "Body", body); } } }
/// <summary> /// 发送 Http 请求 /// </summary> /// <param name="requestUri"></param> /// <param name="httpMethod"></param> /// <param name="bodyArgs"></param> /// <param name="headers"></param> /// <param name="clientName"></param> /// <param name="interceptor"></param> /// <param name="contentType"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <T> SendAsAsync <T>(this string requestUri, HttpMethod httpMethod = default, object bodyArgs = null, Dictionary <string, string> headers = default, string clientName = default, Action <HttpRequestMessage> interceptor = default, string contentType = "application/json", CancellationToken cancellationToken = default) { var response = await requestUri.SendAsync(httpMethod, bodyArgs, headers, clientName, interceptor, contentType, cancellationToken); // 读取流 using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken); // 反序列化结果 var result = await JsonSerializer.DeserializeAsync <T>(responseStream, JsonSerializerUtility.GetDefaultJsonSerializerOptions(), cancellationToken); return(result); }
/// <summary> /// Retrieves data from *.info files within ~\topics folder for particular scenario /// </summary> /// <param name="scenarioId">ID of scenario to retireve topics from</param> /// <returns>Deserialized object from *.info file</returns> public static List <TopicObject> GetTopics(string scenarioId) { var scenarioRootFolder = FindFolderById(scenarioId, PathHelper.GetRepoPath()); EnsureScenarioFoldersExist(scenarioRootFolder); var topicsDirectory = Path.Combine(scenarioRootFolder, "topics"); var serializer = new JsonSerializerUtility(); var result = Directory.GetFiles(topicsDirectory) .Select(topicFile => serializer.DeserializeFromFile <TopicModel>(topicFile)) .Select(topic => topic.ConvertToDto()).ToList(); return(result); }
public void Commit() { if (this.initialized == false) { return; } DirectoryUtility.Backup(this.BasePath); DirectoryUtility.Prepare(this.BasePath); foreach (var item in this.tableInfos) { using (var stream = FileUtility.OpenWrite(this.BasePath, CremaSchema.TableDirectory, infoDirectory, item.Key + jsonExtension)) { JsonSerializerUtility.Write(stream, item.Value); } } foreach (var item in this.tableDatas) { using (var stream = FileUtility.OpenWrite(this.BasePath, CremaSchema.TableDirectory, dataDirectory, item.Key)) { this.OnSerializeTable(stream, item.Value); } } foreach (var item in this.typeInfos) { using (var stream = FileUtility.OpenWrite(this.BasePath, CremaSchema.TypeDirectory, infoDirectory, item.Key + jsonExtension)) { JsonSerializerUtility.Write(stream, item.Value); } } foreach (var item in this.typeDatas) { using (var stream = FileUtility.OpenWrite(this.BasePath, CremaSchema.TypeDirectory, dataDirectory, item.Key)) { this.OnSerializeTable(stream, item.Value); } } var tableInfos = this.tableInfos.Select(item => Path.Combine(CremaSchema.TableDirectory, item.Key)); var typeInfos = this.typeInfos.Select(item => Path.Combine(CremaSchema.TypeDirectory, item.Key)); this.info.ItemList = tableInfos.Concat(typeInfos).ToArray(); this.info.Version = new Version(CremaSchema.MajorVersion, CremaSchema.MinorVersion); this.WriteInfo(); DirectoryUtility.Clean(this.BasePath); }
private void ReadInfo() { var infoPath = Path.Combine(this.BasePath, "info.json"); if (FileUtility.Exists(infoPath) == true) { try { this.info = JsonSerializerUtility.Read <DataServiceItemInfo>(infoPath); } catch (Exception e) { this.logService.Error(e); } } }
/// <summary> /// 如果有异常则抛出 /// </summary> /// <param name="dataValidationResult"></param> public static void AddError(this DataValidationResult dataValidationResult) { if (!dataValidationResult.IsValid) { throw Oops.Oh("[Validation]" + JsonSerializerUtility.Serialize( dataValidationResult.ValidationResults .Select(u => new { MemberNames = u.MemberNames.Any() ? u.MemberNames : new[] { $"{dataValidationResult.MemberOrValue}" }, u.ErrorMessage }) .OrderBy(u => u.MemberNames.First()) .GroupBy(u => u.MemberNames.First()) .ToDictionary(u => u.Key, u => u.Select(c => c.ErrorMessage)))); } }
public void Dispose() { foreach (var item in this.ToArray <DataBase>()) { { var dataBaseInfo = (DataBaseSerializationInfo)item.DataBaseInfo; var filename = FileUtility.Prepare(this.cachePath, $"{item.ID}{databaseExtension}"); JsonSerializerUtility.Write(filename, dataBaseInfo, true); } { var dataBaseState = item.DataBaseState & DataBaseState.IsLoaded; var filename = FileUtility.Prepare(this.cachePath, $"{item.ID}{stateExtension}"); JsonSerializerUtility.Write(filename, dataBaseState, true); } item.Dispose(); } }
private Dictionary <string, DataBaseSerializationInfo> ReadCaches() { var caches = new Dictionary <string, DataBaseSerializationInfo>(); var files = Directory.GetFiles(cachePath, $"*{databaseExtension}"); foreach (var item in files) { try { var dataBaseInfo = JsonSerializerUtility.Read <DataBaseSerializationInfo>(item); caches.Add(dataBaseInfo.Name, dataBaseInfo); } catch (Exception e) { this.cremaHost.Error(e); } } return(caches); }
private Dictionary <string, DataBaseState> ReadStateCaches() { var caches = new Dictionary <string, DataBaseState>(); var files = Directory.GetFiles(cachePath, $"*{stateExtension}"); foreach (var item in files) { try { var dataBaseState = JsonSerializerUtility.Read <DataBaseState>(item); caches.Add(Path.GetFileNameWithoutExtension(item), dataBaseState); } catch (Exception e) { this.cremaHost.Error(e); } } return(caches); }
/// <summary> /// 处理输出状态码 /// </summary> /// <param name="context"></param> /// <param name="statusCode"></param> /// <returns></returns> public async Task OnResponseStatusCodes(HttpContext context, int statusCode) { switch (statusCode) { // 处理 401 状态码 case StatusCodes.Status401Unauthorized: await context.Response.WriteAsJsonAsync(new ApiResponse <object> { Code = StatusCodes.Status401Unauthorized, Success = false, Data = null, Msg = "401 Unauthorized", Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; // 处理 403 状态码 case StatusCodes.Status403Forbidden: await context.Response.WriteAsJsonAsync(new ApiResponse <object> { Code = StatusCodes.Status403Forbidden, Success = false, Data = null, Msg = "403 Forbidden", Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; default: break; } }
/// <summary> /// 发送 Http 请求 /// </summary> /// <param name="requestUri"></param> /// <param name="httpMethod"></param> /// <param name="bodyArgs"></param> /// <param name="headers"></param> /// <param name="clientName"></param> /// <param name="interceptor"></param> /// <param name="contentType">contentType</param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <HttpResponseMessage> SendAsync(this string requestUri, HttpMethod httpMethod = default, object bodyArgs = null, Dictionary <string, string> headers = default, string clientName = default, Action <HttpRequestMessage> interceptor = default, string contentType = "application/json", CancellationToken cancellationToken = default) { // 检查 Url 地址是否有效 var result = requestUri.TryValidate(ValidationTypes.Url); if (!result.IsValid) { throw new InvalidOperationException($"{requestUri} is not a valid url address."); } // 检查 method if (httpMethod == null) { throw new ArgumentNullException(nameof(httpMethod)); } // 创建请求对象 var request = new HttpRequestMessage(httpMethod, requestUri); // 设置请求报文头 if (headers != null && headers.Count > 0) { foreach (var header in headers) { request.Headers.Add(header.Key, header.Value); } } // 设置请求报文参数,排除Get和Head请求 if (httpMethod != HttpMethod.Get && httpMethod != HttpMethod.Head && bodyArgs != null) { string body; // 处理 json 类型 if (contentType.Contains("json")) { body = JsonSerializerUtility.Serialize(bodyArgs); } // 处理 xml 类型 else if (contentType.Contains("xml")) { var xmlSerializer = new XmlSerializer(bodyArgs.GetType()); var buffer = new StringBuilder(); using var writer = new StringWriter(buffer); xmlSerializer.Serialize(writer, bodyArgs); body = buffer.ToString(); } // 其他类型 else { body = bodyArgs.ToString(); } if (!string.IsNullOrEmpty(body)) { var httpContent = new StringContent(body, Encoding.UTF8); // 设置内容类型 httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); request.Content = httpContent; // 打印请求地址 App.PrintToMiniProfiler(MiniProfilerCategory, "Body", body); } } // 请求之前拦截 interceptor?.Invoke(request); // 打印请求地址 App.PrintToMiniProfiler(MiniProfilerCategory, "Beginning", $"{request.Method} {request.RequestUri.AbsoluteUri}"); // 创建 HttpClient 对象 var clientFactory = App.GetService <IHttpClientFactory>(); if (clientFactory == null) { throw new ArgumentNullException("Please register for RemoteRequest service first: services.AddRemoteRequest();"); } var httpClient = string.IsNullOrEmpty(clientName) ? clientFactory.CreateClient() : clientFactory.CreateClient(clientName); // 发送请求 var response = await httpClient.SendAsync(request, cancellationToken); if (response.IsSuccessStatusCode) { return(response); } else { // 读取错误数据 var errorMessage = await response.Content.ReadAsStringAsync(cancellationToken); // 打印失败消息 App.PrintToMiniProfiler(MiniProfilerCategory, "Failed", errorMessage, isError: true); // 抛出请求异常 throw new HttpRequestException(errorMessage); } }
private void Initialize() { this.Dispatcher.CheckAccess(); var error = false; try { if (this.info.Revision != 0) { foreach (var item in this.info.ItemList) { if (item.StartsWith(CremaSchema.TableDirectory) == true) { var tableName = Path.GetFileName(item); using (var stream = FileUtility.OpenRead(this.BasePath, CremaSchema.TableDirectory, infoDirectory, tableName + jsonExtension)) { this.tableInfos.Add(tableName, JsonSerializerUtility.Read <TableInfo>(stream)); } using (var stream = FileUtility.OpenRead(this.BasePath, CremaSchema.TableDirectory, dataDirectory, tableName)) { this.tableDatas.Add(tableName, this.OnDeserializeTable(stream)); } } else if (item.StartsWith(CremaSchema.TypeDirectory) == true) { var typeName = Path.GetFileName(item); using (var stream = FileUtility.OpenRead(this.BasePath, CremaSchema.TypeDirectory, infoDirectory, typeName + jsonExtension)) { this.typeInfos.Add(typeName, JsonSerializerUtility.Read <TypeInfo>(stream)); } using (var stream = FileUtility.OpenRead(this.BasePath, CremaSchema.TypeDirectory, dataDirectory, typeName)) { this.typeDatas.Add(typeName, this.OnDeserializeType(stream)); } } } } else { error = true; } } catch { error = true; } if (error == true) { var result = this.dataBase.Dispatcher.Invoke(() => { var revision = this.dataBase.DataBaseInfo.Revision; var contains = this.dataBase.Contains(this.Authentication); if (contains == false) { this.dataBase.Enter(this.Authentication); } var dataSet = this.dataBase.GetDataSet(this.Authentication, -1); if (contains == false) { this.dataBase.Leave(this.Authentication); } return(new Tuple <long, CremaDataSet>(revision, dataSet)); }); this.Serialize(result.Item2, result.Item1); } this.initialized = true; }
/// <summary> /// 设置方法体 /// </summary> /// <param name="request"></param> /// <param name="bodyArgs"></param> /// <param name="bodyContentTypeOptions"></param> /// <param name="jsonNamingPolicyOptions"></param> /// <param name="contentType"></param> internal static void SetHttpRequestBody(HttpRequestMessage request, object bodyArgs, HttpContentTypeOptions bodyContentTypeOptions, JsonNamingPolicyOptions jsonNamingPolicyOptions, string contentType) { // 处理 body 内容 HttpContent httpContent; switch (bodyContentTypeOptions) { case HttpContentTypeOptions.StringContent: case HttpContentTypeOptions.JsonStringContent: case HttpContentTypeOptions.XmlStringContent: string bodyContent; // application/json;text/json;application/*+json if (bodyContentTypeOptions == HttpContentTypeOptions.JsonStringContent) { // 配置 Json 命名策略 var jsonSerializerOptions = JsonSerializerUtility.GetDefaultJsonSerializerOptions(); jsonSerializerOptions.PropertyNamingPolicy = jsonNamingPolicyOptions switch { JsonNamingPolicyOptions.CamelCase => JsonNamingPolicy.CamelCase, JsonNamingPolicyOptions.Null => null, _ => null }; bodyContent = JsonSerializerUtility.Serialize(bodyArgs, jsonSerializerOptions); } // application/xml;text/xml;application/*+xml else if (bodyContentTypeOptions == HttpContentTypeOptions.XmlStringContent) { var xmlSerializer = new XmlSerializer(bodyArgs.GetType()); var buffer = new StringBuilder(); using var writer = new StringWriter(buffer); xmlSerializer.Serialize(writer, bodyArgs); bodyContent = buffer.ToString(); } // none else { bodyContent = bodyArgs.ToString(); } httpContent = new StringContent(bodyContent, Encoding.UTF8); break; // 处理 x-www-form-urlencoded case HttpContentTypeOptions.FormUrlEncodedContent: Dictionary <string, string> formDataDic = new(); if (bodyArgs is Dictionary <string, string> dic) { formDataDic = dic; } else { var bodyArgsType = bodyArgs.GetType(); // 只有类和匿名类才处理 if (bodyArgsType.IsClass || bodyArgsType.IsAnonymous()) { var properties = bodyArgsType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { formDataDic.Add(prop.Name, prop.GetValue(bodyArgs)?.ToString()); } } } httpContent = new FormUrlEncodedContent(formDataDic); break; // 处理 multipart/form-data case HttpContentTypeOptions.MultipartFormDataContent: default: throw new NotImplementedException("Please use RequestInterceptor to set."); } // 设置内容 if (httpContent != null) { httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); request.Content = httpContent; } }
private void WriteInfo() { var infoPath = Path.Combine(this.BasePath, "info.json"); JsonSerializerUtility.Write(infoPath, this.info, true); }
/// <summary> /// 拦截异步带返回值方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="method"></param> /// <param name="args"></param> /// <returns></returns> public override async Task <T> InvokeAsyncT <T>(MethodInfo method, object[] args) { // 发送请求 var(response, httpMethodAttribute) = await SendAsync(method, args); // 判断是否请求成功 if (response.IsSuccessStatusCode) { // 打印成功消息 App.PrintToMiniProfiler(MiniProfilerCategory, "Succeeded"); // 处理返回值类型 switch (httpMethodAttribute.ResponseType) { // 对象类型或流类型 case ResponseType.Object: case ResponseType.Stream: var responseStream = await response.Content.ReadAsStreamAsync(); // 流类型 if (httpMethodAttribute.ResponseType == ResponseType.Stream) { return((T)(object)responseStream); } // 对象类型 else { var result = await JsonSerializer.DeserializeAsync <T>(responseStream, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); // 释放流 await responseStream.DisposeAsync(); return(result); } // 文本类型 case ResponseType.Text: var responseText = await response.Content.ReadAsStringAsync(); return((T)(object)responseText); // Byte 数组类型 case ResponseType.ByteArray: var responseByteArray = await response.Content.ReadAsByteArrayAsync(); return((T)(object)responseByteArray); // 无效类型 default: throw new InvalidCastException("Invalid response type setting."); } } else { throw (await CreateRequestException(response)); } }
private static void WriteAccessInfo(string accessInfoPath, AccessInfo accessInfo) { JsonSerializerUtility.Write(accessInfoPath, (AccessSerializationInfo)accessInfo, true); }