internal static object StringToType( TypeConfig typeConfig, StringSegment strType, EmptyCtorDelegate ctorFn, Dictionary <HashedStringSegment, TypeAccessor> typeAccessorMap) { var index = 0; var type = typeConfig.Type; if (!strType.HasValue) { return(null); } //if (!Serializer.EatMapStartChar(strType, ref index)) if (strType.GetChar(index++) != JsWriter.MapStartChar) { throw DeserializeTypeRef.CreateSerializationError(type, strType.Value); } if (JsonTypeSerializer.IsEmptyMap(strType)) { return(ctorFn()); } object instance = null; var propertyResolver = JsConfig.PropertyConvention == PropertyConvention.Lenient ? ParseUtils.LenientPropertyNameResolver : ParseUtils.DefaultPropertyNameResolver; var strTypeLength = strType.Length; while (index < strTypeLength) { var propertyName = Serializer.EatMapKey(strType, ref index); //Serializer.EatMapKeySeperator(strType, ref index); index++; var propertyValueStr = Serializer.EatValue(strType, ref index); var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1; if (possibleTypeInfo && propertyName == new StringSegment(JsWriter.TypeAttr)) { var explicitTypeName = Serializer.ParseString(propertyValueStr); var explicitType = JsConfig.TypeFinder(explicitTypeName); if (explicitType == null || explicitType.IsInterface() || explicitType.IsAbstract()) { Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr); } else if (!type.IsAssignableFromType(explicitType)) { Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr); } else { JsWriter.AssertAllowedRuntimeType(explicitType); instance = explicitType.CreateInstance(); } if (instance != null) { //If __type info doesn't match, ignore it. if (!type.InstanceOfType(instance)) { instance = null; } else { var derivedType = instance.GetType(); if (derivedType != type) { var derivedTypeConfig = new TypeConfig(derivedType); var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer); if (map != null) { typeAccessorMap = map; } } } } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); if (index != strType.Length) { index++; } continue; } if (instance == null) { instance = ctorFn(); } var typeAccessor = propertyResolver.GetTypeAccessorForProperty(propertyName, typeAccessorMap); var propType = possibleTypeInfo && propertyValueStr.GetChar(0) == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr) : null; if (propType != null) { try { if (typeAccessor != null) { var parseFn = Serializer.GetParseStringSegmentFn(propType); var propertyValue = parseFn(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.Value, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); if (index != strType.Length) { index++; } continue; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError(instance, propType, propertyName.Value, propertyValueStr.Value, e); } if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException(propertyName.Value, propertyValueStr.Value, propType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr); } } } if (typeAccessor?.GetProperty != null && typeAccessor.SetProperty != null) { try { var propertyValue = typeAccessor.GetProperty(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.Value, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } catch (NotSupportedException) { throw; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError(instance, propType ?? typeAccessor.PropertyType, propertyName.Value, propertyValueStr.Value, e); } if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException(propertyName.Value, propertyValueStr.Value, propType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr); } } } else { // the property is not known by the DTO typeConfig.OnDeserializing?.Invoke(instance, propertyName.Value, propertyValueStr); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); if (index != strType.Length) { index++; } } return(instance); }
private static bool Init() { if (!typeof(T).IsClass() && !typeof(T).IsInterface() && !JsConfig.TreatAsRefType(typeof(T))) { return(false); } var propertyInfos = TypeConfig <T> .Properties; var fieldInfos = JsConfig.IncludePublicFields ? TypeConfig <T> .Fields : new FieldInfo[0]; var propertyNamesLength = propertyInfos.Length; var fieldNamesLength = fieldInfos.Length; PropertyWriters = new TypePropertyWriter[propertyNamesLength + fieldNamesLength]; if (propertyNamesLength + fieldNamesLength == 0 && !JsState.IsWritingDynamic) { return(typeof(T).IsDto()); } // NOTE: very limited support for DataContractSerialization (DCS) // NOT supporting Serializable // support for DCS is intended for (re)Name of properties and Ignore by NOT having a DataMember present var isDataContract = typeof(T).IsDto(); for (var i = 0; i < propertyNamesLength; i++) { var propertyInfo = propertyInfos[i]; string propertyName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyReflectedName; int propertyOrder = -1; var propertyType = propertyInfo.PropertyType; var defaultValue = propertyType.GetDefaultValue(); bool propertySuppressDefaultConfig = defaultValue != null && propertyType.IsValueType() && JsConfig.HasSerializeFn.Contains(propertyType); bool propertySuppressDefaultAttribute = false; if (isDataContract) { var dcsDataMember = propertyInfo.GetDataMember(); if (dcsDataMember == null) { continue; } propertyName = dcsDataMember.Name ?? propertyInfo.Name; propertyNameCLSFriendly = dcsDataMember.Name ?? propertyName.ToCamelCase(); propertyNameLowercaseUnderscore = dcsDataMember.Name ?? propertyName.ToLowercaseUnderscore(); propertyReflectedName = dcsDataMember.Name ?? propertyInfo.ReflectedType.Name; propertyOrder = dcsDataMember.Order; propertySuppressDefaultAttribute = !dcsDataMember.EmitDefaultValue; } else { propertyName = propertyInfo.Name; propertyNameCLSFriendly = propertyName.ToCamelCase(); propertyNameLowercaseUnderscore = propertyName.ToLowercaseUnderscore(); propertyReflectedName = propertyInfo.ReflectedType.Name; } PropertyWriters[i] = new TypePropertyWriter ( propertyName, propertyReflectedName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyOrder, propertySuppressDefaultConfig, propertySuppressDefaultAttribute, propertyInfo.GetValueGetter <T>(), Serializer.GetWriteFn(propertyType), propertyType.GetDefaultValue() ); } for (var i = 0; i < fieldNamesLength; i++) { var fieldInfo = fieldInfos[i]; string propertyName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyReflectedName; int propertyOrder = -1; var propertyType = fieldInfo.FieldType; var defaultValue = propertyType.GetDefaultValue(); bool propertySuppressDefaultConfig = defaultValue != null && propertyType.IsValueType() && JsConfig.HasSerializeFn.Contains(propertyType); bool propertySuppressDefaultAttribute = false; if (isDataContract) { var dcsDataMember = fieldInfo.GetDataMember(); if (dcsDataMember == null) { continue; } propertyName = dcsDataMember.Name ?? fieldInfo.Name; propertyNameCLSFriendly = dcsDataMember.Name ?? propertyName.ToCamelCase(); propertyNameLowercaseUnderscore = dcsDataMember.Name ?? propertyName.ToLowercaseUnderscore(); propertyReflectedName = dcsDataMember.Name ?? fieldInfo.ReflectedType.Name; propertyOrder = dcsDataMember.Order; propertySuppressDefaultAttribute = !dcsDataMember.EmitDefaultValue; } else { propertyName = fieldInfo.Name; propertyNameCLSFriendly = propertyName.ToCamelCase(); propertyNameLowercaseUnderscore = propertyName.ToLowercaseUnderscore(); propertyReflectedName = fieldInfo.ReflectedType.Name; } PropertyWriters[i + propertyNamesLength] = new TypePropertyWriter ( propertyName, propertyReflectedName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyOrder, propertySuppressDefaultConfig, propertySuppressDefaultAttribute, fieldInfo.GetValueGetter <T>(), Serializer.GetWriteFn(propertyType), defaultValue ); } PropertyWriters = PropertyWriters.OrderBy(x => x.propertyOrder).ToArray(); return(true); }
protected ServiceStackHost(string serviceName, params Assembly[] assembliesWithServices) { this.StartedAt = DateTime.UtcNow; ServiceName = serviceName; AppSettings = new AppSettings(); Container = new Container { DefaultOwner = Owner.External }; ServiceAssemblies = assembliesWithServices.ToList(); ContentTypes = new ContentTypes(); RestPaths = new List <RestPath>(); Routes = new ServiceRoutes(this); Metadata = new ServiceMetadata(RestPaths); PreRequestFilters = new List <Action <IRequest, IResponse> >(); RequestConverters = new List <Func <IRequest, object, Task <object> > >(); ResponseConverters = new List <Func <IRequest, object, Task <object> > >(); GlobalRequestFilters = new List <Action <IRequest, IResponse, object> >(); GlobalRequestFiltersAsync = new List <Func <IRequest, IResponse, object, Task> >(); GlobalTypedRequestFilters = new Dictionary <Type, ITypedFilter>(); GlobalResponseFilters = new List <Action <IRequest, IResponse, object> >(); GlobalResponseFiltersAsync = new List <Func <IRequest, IResponse, object, Task> >(); GlobalTypedResponseFilters = new Dictionary <Type, ITypedFilter>(); GlobalMessageRequestFilters = new List <Action <IRequest, IResponse, object> >(); GlobalMessageRequestFiltersAsync = new List <Func <IRequest, IResponse, object, Task> >(); GlobalTypedMessageRequestFilters = new Dictionary <Type, ITypedFilter>(); GlobalMessageResponseFilters = new List <Action <IRequest, IResponse, object> >(); GlobalMessageResponseFiltersAsync = new List <Func <IRequest, IResponse, object, Task> >(); GlobalTypedMessageResponseFilters = new Dictionary <Type, ITypedFilter>(); GatewayRequestFilters = new List <Action <IRequest, object> >(); GatewayRequestFiltersAsync = new List <Func <IRequest, object, Task> >(); GatewayResponseFilters = new List <Action <IRequest, object> >(); GatewayResponseFiltersAsync = new List <Func <IRequest, object, Task> >(); ViewEngines = new List <IViewEngine>(); ServiceExceptionHandlers = new List <HandleServiceExceptionDelegate>(); ServiceExceptionHandlersAsync = new List <HandleServiceExceptionAsyncDelegate>(); UncaughtExceptionHandlers = new List <HandleUncaughtExceptionDelegate>(); UncaughtExceptionHandlersAsync = new List <HandleUncaughtExceptionAsyncDelegate>(); BeforeConfigure = new List <Action <ServiceStackHost> >(); AfterConfigure = new List <Action <ServiceStackHost> >(); AfterInitCallbacks = new List <Action <IAppHost> >(); OnDisposeCallbacks = new List <Action <IAppHost> >(); OnEndRequestCallbacks = new List <Action <IRequest> >(); AddVirtualFileSources = new List <IVirtualPathProvider>(); RawHttpHandlers = new List <Func <IHttpRequest, IHttpHandler> > { ReturnRedirectHandler, ReturnRequestInfoHandler, }; CatchAllHandlers = new List <HttpHandlerResolverDelegate>(); FallbackHandlers = new List <HttpHandlerResolverDelegate>(); CustomErrorHttpHandlers = new Dictionary <HttpStatusCode, IServiceStackHandler> { { HttpStatusCode.Forbidden, new ForbiddenHttpHandler() }, { HttpStatusCode.NotFound, new NotFoundHttpHandler() }, }; StartUpErrors = new List <ResponseStatus>(); AsyncErrors = new List <ResponseStatus>(); PluginsLoaded = new List <string>(); Plugins = new List <IPlugin> { new HtmlFormat(), new CsvFormat(), new PredefinedRoutesFeature(), new MetadataFeature(), new NativeTypesFeature(), new HttpCacheFeature(), new RequestInfoFeature(), new SpanFormats(), }; ExcludeAutoRegisteringServiceTypes = new HashSet <Type> { typeof(AuthenticateService), typeof(RegisterService), typeof(AssignRolesService), typeof(UnAssignRolesService), typeof(NativeTypesService), typeof(PostmanService), typeof(TemplateHotReloadService), typeof(HotReloadFilesService), typeof(TemplateApiPagesService), typeof(TemplateMetadataDebugService), typeof(ServerEventsSubscribersService), typeof(ServerEventsUnRegisterService), }; JsConfig.InitStatics(); }
public void SetUp() { JsConfig.Reset(); _localTimezoneOffset = TimeZoneInfo.Local.BaseUtcOffset.Hours.ToString("00") + TimeZoneInfo.Local.BaseUtcOffset.Minutes.ToString("00"); }
public void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName) { if (EndpointHost.ApplyPreRequestFilters(httpReq, httpRes)) { return; } List <KeyValuePair <string, object> > configInfo = new List <KeyValuePair <string, object> >(); if (AppHostBase.Instance != null) { configInfo.Add(new KeyValuePair <string, object>("StartUpTime", AppHostBase.Instance.StartUpTime)); } if (AppHostHttpListenerBase.Instance != null) { configInfo.Add(new KeyValuePair <string, object>("StartUpTime", AppHostHttpListenerBase.Instance.StartUpTime)); } configInfo.Add(new KeyValuePair <string, object>("AppId", ServiceUtils.AppId)); configInfo.Add(new KeyValuePair <string, object>("IPv4", ServiceUtils.HostIP)); configInfo.Add(new KeyValuePair <string, object>("MachineName", ServiceUtils.MachineName)); configInfo.Add(new KeyValuePair <string, object>("SOA.CurrentEnv", EnvironmentUtility.CurrentEnv)); var metadata = EndpointHost.MetadataMap[httpReq.ServicePath]; configInfo.Add(new KeyValuePair <string, object>("SOA.ServiceName", metadata.ServiceName)); configInfo.Add(new KeyValuePair <string, object>("SOA.ServiceNamespace", metadata.ServiceNamespace)); configInfo.Add(new KeyValuePair <string, object>("SOA.ServiceTestSubEnv", metadata.ServiceTestSubEnv ?? "null")); configInfo.Add(new KeyValuePair <string, object>( ServiceMetadata.DefaultLogErrorWithRequestInfoSettingKey, metadata.LogErrorWithRequestInfo)); configInfo.Add(new KeyValuePair <string, object>( ServiceMetadata.DefaultLogCommonRequestInfoSettingKey, metadata.LogCommonRequestInfo)); configInfo.Add(new KeyValuePair <string, object>( ServiceMetadata.DefaultLogH5HeadExtensionDataSettingKey, metadata.LogH5HeadExtensionData)); bool circuitBreakerForceClosed = metadata.CircuitBreakerForceClosed; configInfo.Add(new KeyValuePair <string, object>(ServiceMetadata.DefaultCircuitBreakerForceClosedSettingKey, circuitBreakerForceClosed)); Dictionary <string, double> timeoutMap = new Dictionary <string, double>(); foreach (Operation operation in metadata.Operations) { timeoutMap.Add(operation.Name, operation.HystrixCommand.GetExecutionTimeout().TotalMilliseconds); } configInfo.Add(new KeyValuePair <string, object>(ServiceMetadata.DefaultOperationTimeoutMapSettingKey, timeoutMap)); configInfo.Add(new KeyValuePair <string, object>( ServiceMetadata.DefaultUseChunkedTransferEncodingSettingKey, metadata.UseChunkedTransferEncoding)); configInfo.Add(new KeyValuePair <string, object>("SOA.FxConfigWebServiceUtils.Enabled", AntFxConfigWebServiceUtils.Enabled)); configInfo.Add(new KeyValuePair <string, object>("SOA.FxConfigWebServiceUtils.ApiUrl", AntFxConfigWebServiceUtils.ConfigWebServiceApiUrl)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MinGlobalDefaultTimeout", HystrixCommandHelper.MinGlobalDefaultCircuitBreakerTimeoutSetting.TotalMilliseconds.ToString())); configInfo.Add(new KeyValuePair <string, object>( "SOA.GlobalDefaultTimeout", HystrixCommandHelper.GlobalDefaultCircuitBreakerTimeoutSetting.HasValue ? HystrixCommandHelper.GlobalDefaultCircuitBreakerTimeoutSetting.Value.TotalMilliseconds.ToString() : null)); configInfo.Add(new KeyValuePair <string, object>( "SOA.FrameworkDefaultTimeout", HystrixPropertiesCommandDefault.DefaultExecutionIsolationThreadTimeout.TotalMilliseconds.ToString())); configInfo.Add(new KeyValuePair <string, object>( "SOA.FrameworkDefaultConnectionMaxRequestCount", ServiceMetadata.FrameworkDefaultConnectionMaxRequestCount)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MinConnectionMaxRequestCount", ServiceMetadata.MinConnectionMaxRequestCount)); configInfo.Add(new KeyValuePair <string, object>( "SOA.CheckConnectionMaxRequestCount", metadata.CheckConnectionMaxRequestCount)); configInfo.Add(new KeyValuePair <string, object>( "SOA.ConnectionMaxRequestCount", metadata.ConnectionMaxRequestCount)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.RequestLogMaxSize", MessageLogConfig.RequestLogMaxSize)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.ResponseLogMaxSize", MessageLogConfig.ResponseLogMaxSize)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.FrameworkDefalut.Test", MessageLogConfig.FrameworkDefalutMessageLogConfigOfTestEnv)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.FrameworkDefalut.Uat", MessageLogConfig.FrameworkDefalutMessageLogConfigOfUatEnv)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.FrameworkDefalut.Prod", MessageLogConfig.FrameworkDefalutMessageLogConfigOfProdEnv)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.FrameworkDefalut.Null", MessageLogConfig.FrameworkDefalutMessageLogConfigOfNullEnv)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.FrameworkDefault.Current", MessageLogConfig.CurrentFrameworkDefaultMessageLogConfig)); configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.Service", metadata.ServiceMessageLogConfig)); var operationMessageConfigs = from operation in metadata.Operations select new { operation.Name, operation.OperationMessageLogConfig, }; configInfo.Add(new KeyValuePair <string, object>( "SOA.MessageLogConfig.Operation", operationMessageConfigs)); configInfo.Add(new KeyValuePair <string, object>( "SOA.DeserializeRequestUseMemoryStream", metadata.DeserializeRequestUseMemoryStream)); configInfo.Add(new KeyValuePair <string, object>( "SOA.LogPopulateExceptionAsWarning", ReflectionUtils.LogPopulateExceptionAsWarning)); foreach (IHasConfigInfo configInfoOwner in ConfigInfoOwners) { configInfo.AddRange(configInfoOwner.GetConfigInfo(httpReq.ServicePath)); } using (JsConfigScope scope = JsConfig.BeginScope()) { scope.ExcludeTypeInfo = true; scope.DateHandler = JsonDateHandler.LongDateTime; httpRes.ContentType = "application/json"; httpRes.Write(WrappedJsonSerializer.Instance.SerializeToString(configInfo)); } }
internal static object StringToType( TypeConfig typeConfig, StringSegment strType, EmptyCtorDelegate ctorFn, Dictionary <HashedStringSegment, TypeAccessor> typeAccessorMap) { var index = 0; var type = typeConfig.Type; if (!strType.HasValue) { return(null); } var buffer = strType.Buffer; var offset = strType.Offset; var strTypeLength = strType.Length; // if (!Serializer.EatMapStartChar(strType, ref index)) for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } // Whitespace inline if (buffer[offset + index] != JsWriter.MapStartChar) { throw DeserializeTypeRef.CreateSerializationError(type, strType.Value); } index++; if (JsonTypeSerializer.IsEmptyMap(strType, index)) { return(ctorFn()); } object instance = null; var propertyResolver = JsConfig.PropertyConvention == PropertyConvention.Lenient ? ParseUtils.LenientPropertyNameResolver : ParseUtils.DefaultPropertyNameResolver; while (index < strTypeLength) { var propertyName = JsonTypeSerializer.ParseJsonString(strType, ref index); // Serializer.EatMapKeySeperator(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } // Whitespace inline if (strTypeLength != index) { index++; } var propertyValueStr = Serializer.EatValue(strType, ref index); var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1; // if we already have an instance don't check type info, because then we will have a half deserialized object // we could throw here or just use the existing instance. if (instance == null && possibleTypeInfo && propertyName == typeAttr) { var explicitTypeName = Serializer.ParseString(propertyValueStr); var explicitType = JsConfig.TypeFinder(explicitTypeName); if (explicitType == null || explicitType.IsInterface || explicitType.IsAbstract) { Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr); } else if (!type.IsAssignableFrom(explicitType)) { Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr); } else { JsWriter.AssertAllowedRuntimeType(explicitType); instance = explicitType.CreateInstance(); } if (instance != null) { // If __type info doesn't match, ignore it. if (!type.IsInstanceOfType(instance)) { instance = null; } else { var derivedType = instance.GetType(); if (derivedType != type) { var derivedTypeConfig = new TypeConfig(derivedType); var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer); if (map != null) { typeAccessorMap = map; } } } } Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); continue; } if (instance == null) { instance = ctorFn(); } var typeAccessor = propertyResolver.GetTypeAccessorForProperty(propertyName, typeAccessorMap); var propType = possibleTypeInfo && propertyValueStr.GetChar(0) == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr) : null; if (propType != null) { try { if (typeAccessor != null) { // var parseFn = Serializer.GetParseFn(propType); var parseFn = JsonReader.GetParseStringSegmentFn(propType); var propertyValue = parseFn(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.Value, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } // Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } // Whitespace inline if (index != strTypeLength) { var success = buffer[offset + index] == JsWriter.ItemSeperator || buffer[offset + index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } } // Whitespace inline } continue; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError( instance, propType, propertyName.Value, propertyValueStr.Value, e); } if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException( propertyName.Value, propertyValueStr.Value, propType, e); } else { Tracer.Instance.WriteWarning( "WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr.Value); } } } if (typeAccessor?.GetProperty != null && typeAccessor.SetProperty != null) { try { var propertyValue = typeAccessor.GetProperty(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.Value, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } catch (NotSupportedException) { throw; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError( instance, propType ?? typeAccessor.PropertyType, propertyName.Value, propertyValueStr.Value, e); } if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException( propertyName.Value, propertyValueStr.Value, typeAccessor.PropertyType, e); } else { Tracer.Instance.WriteWarning( "WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr.Value); } } } else { // the property is not known by the DTO typeConfig.OnDeserializing?.Invoke(instance, propertyName.Value, propertyValueStr.Value); } // Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } // Whitespace inline if (index != strType.Length) { var success = buffer[offset + index] == JsWriter.ItemSeperator || buffer[offset + index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[offset + index])) { break; } } } // Whitespace inline } } return(instance); }
public object Get(OpenApiSpecification request) { var map = HostContext.ServiceController.RestPathMap; var paths = new List <RestPath>(); var basePath = new Uri(base.Request.GetBaseUrl()); var meta = HostContext.Metadata; foreach (var key in map.Keys) { var restPaths = map[key]; var visiblePaths = restPaths.Where(x => meta.IsVisible(Request, Format.Json, x.RequestType.Name)); paths.AddRange(visiblePaths); } var definitions = new Dictionary <string, OpenApiSchema> { { "Object", new OpenApiSchema { Description = "Object", Type = OpenApiType.Object, Properties = new OrderedDictionary <string, OpenApiProperty>() } }, }; foreach (var restPath in paths.SelectMany(x => x.Verbs.Select(y => new { Value = x, Verb = y }))) { ParseDefinitions(definitions, restPath.Value.RequestType, restPath.Value.Path, restPath.Verb); } var tags = new Dictionary <string, OpenApiTag>(); var apiPaths = ParseOperations(paths, definitions, tags); var result = new OpenApiDeclaration { Info = new OpenApiInfo { Title = HostContext.ServiceName, Version = HostContext.Config.ApiVersion, }, Paths = apiPaths, BasePath = basePath.AbsolutePath, Schemes = new List <string> { basePath.Scheme }, //TODO: get https from config Host = basePath.Authority, Consumes = new List <string> { "application/json" }, Produces = new List <string> { "application/json" }, Definitions = definitions, Tags = tags.Values.OrderBy(x => x.Name).ToList(), Parameters = new Dictionary <string, OpenApiParameter> { { "Accept", GetAcceptHeaderParameter() } }, SecurityDefinitions = new Dictionary <string, OpenApiSecuritySchema> { { "basic", new OpenApiSecuritySchema { Type = "basic" } } } }; if (OperationFilter != null) { apiPaths.Each(x => GetOperations(x.Value).Each(o => OperationFilter(o.Item1, o.Item2))); } ApiDeclarationFilter?.Invoke(result); return(new HttpResult(result) { ResultScope = () => JsConfig.With(includeNullValues: false) }); }
public override void Configure(Container container) { Plugins.Add(new MiniProfilerFeature()); Plugins.Add(new RazorFormat()); Plugins.Add(new ServerEventsFeature { OnCreated = (sub, req) => { sub.ServerArgs = new Dictionary <string, string> { { "server-arg", "1" } }; } }); container.Register(new DataSource()); var UsePostgreSql = false; if (UsePostgreSql) { container.Register <IDbConnectionFactory>( new OrmLiteConnectionFactory( Environment.GetEnvironmentVariable("PGSQL_CONNECTION") ?? "Server=localhost;Port=5432;User Id=test;Password=test;Database=test;Pooling=true;MinPoolSize=0;MaxPoolSize=200", PostgreSqlDialect.Provider) { ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current) }); } else { container.Register <IDbConnectionFactory>( new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider) { ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current) }); } using (var db = container.Resolve <IDbConnectionFactory>().Open()) { db.DropAndCreateTable <Rockstar>(); db.Insert(Rockstar.SeedData); } JsConfig.Init(new Text.Config { TextCase = TextCase.CamelCase }); //Register a external dependency-free container.Register <ICacheClient>(new MemoryCacheClient()); //Enable Authentication an Registration ConfigureAuth(container); //Create your own custom User table using (var db = container.Resolve <IDbConnectionFactory>().Open()) db.DropAndCreateTable <UserTable>(); SetConfig(new HostConfig { DebugMode = true, AddRedirectParamsToQueryString = true, }); }
public void TestFixtureTearDown() { JsConfig.Reset(); }
private ParseStringDelegate GetCoreParseFn <T>() { var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); if (JsConfig <T> .HasDeserializeFn) { return(value => JsConfig <T> .ParseFn(Serializer, value)); } if (type.IsEnum()) { return(x => Enum.Parse(type, Serializer.UnescapeSafeString(x), true)); } if (type == typeof(string)) { return(Serializer.UnescapeString); } if (type == typeof(object)) { return(DeserializeType <TSerializer> .ObjectStringToType); } var specialParseFn = ParseUtils.GetSpecialParseMethod(type); if (specialParseFn != null) { return(specialParseFn); } if (type.IsEnum()) { return(x => Enum.Parse(type, x, true)); } if (type.IsArray) { return(DeserializeArray <T, TSerializer> .Parse); } var builtInMethod = DeserializeBuiltin <T> .Parse; if (builtInMethod != null) { return(value => builtInMethod(Serializer.UnescapeSafeString(value))); } if (type.HasGenericType()) { if (type.IsOrHasGenericInterfaceTypeOf(typeof(IList <>))) { return(DeserializeList <T, TSerializer> .Parse); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IDictionary <,>))) { return(DeserializeDictionary <TSerializer> .GetParseMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(ICollection <>))) { return(DeserializeCollection <TSerializer> .GetParseMethod(type)); } if (type.HasAnyTypeDefinitionsOf(typeof(Queue <>)) || type.HasAnyTypeDefinitionsOf(typeof(Stack <>))) { return(DeserializeSpecializedCollections <T, TSerializer> .Parse); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(KeyValuePair <,>))) { return(DeserializeKeyValuePair <TSerializer> .GetParseMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IEnumerable <>))) { return(DeserializeEnumerable <T, TSerializer> .Parse); } } #if NET40 if (typeof(T).IsAssignableFrom(typeof(System.Dynamic.IDynamicMetaObjectProvider)) || typeof(T).HasInterface(typeof(System.Dynamic.IDynamicMetaObjectProvider))) { return(DeserializeDynamic <TSerializer> .Parse); } #endif var isDictionary = typeof(T) != typeof(IEnumerable) && (typeof(T).AssignableFrom(typeof(IDictionary)) || typeof(T).HasInterface(typeof(IDictionary))); if (isDictionary) { return(DeserializeDictionary <TSerializer> .GetParseMethod(type)); } var isEnumerable = typeof(T).AssignableFrom(typeof(IEnumerable)) || typeof(T).HasInterface(typeof(IEnumerable)); if (isEnumerable) { var parseFn = DeserializeSpecializedCollections <T, TSerializer> .Parse; if (parseFn != null) { return(parseFn); } } if (type.IsValueType()) { var staticParseMethod = StaticParseMethod <T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value))); } } else { var staticParseMethod = StaticParseRefTypeMethod <TSerializer, T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value))); } } var typeConstructor = DeserializeType <TSerializer> .GetParseMethod(TypeConfig <T> .GetState()); if (typeConstructor != null) { return(typeConstructor); } var stringConstructor = DeserializeTypeUtils.GetParseMethod(type); if (stringConstructor != null) { return(stringConstructor); } return(DeserializeType <TSerializer> .ParseAbstractType <T>); }
public void SetUp() { JsConfig.Reset(); JsConfig <ICat> .ExcludeTypeInfo = false; }
public static void RegisterConverter <From, To>(Func <From, To> converter) { JsConfig.InitStatics(); converters[Tuple.Create(typeof(From), typeof(To))] = x => converter((From)x); }
public static IDictionary <TKey, TValue> ParseDictionary <TKey, TValue>( ReadOnlySpan <char> value, Type createMapType, ParseStringSpanDelegate parseKeyFn, ParseStringSpanDelegate parseValueFn) { if (value.IsEmpty) { return(null); } var to = (createMapType == null) ? new Dictionary <TKey, TValue>() : (IDictionary <TKey, TValue>)createMapType.CreateInstance(); var objDeserializer = Json.JsonTypeSerializer.Instance.ObjectDeserializer; if (to is Dictionary <string, object> && objDeserializer != null && typeof(TSerializer) == typeof(Json.JsonTypeSerializer)) { return((IDictionary <TKey, TValue>)objDeserializer(value)); } var config = JsConfig.GetConfig(); var tryToParseItemsAsDictionaries = config.ConvertObjectTypesIntoStringDictionary && typeof(TValue) == typeof(object); var tryToParseItemsAsPrimitiveTypes = config.TryToParsePrimitiveTypeValues && typeof(TValue) == typeof(object); var index = VerifyAndGetStartIndex(value, createMapType); if (Json.JsonTypeSerializer.IsEmptyMap(value, index)) { return(to); } var valueLength = value.Length; while (index < valueLength) { var keyValue = Serializer.EatMapKey(value, ref index); Serializer.EatMapKeySeperator(value, ref index); var elementStartIndex = index; var elementValue = Serializer.EatTypeValue(value, ref index); if (keyValue.IsNullOrEmpty()) { continue; } TKey mapKey = (TKey)parseKeyFn(keyValue); if (tryToParseItemsAsDictionaries) { Serializer.EatWhitespace(value, ref elementStartIndex); if (elementStartIndex < valueLength && value[elementStartIndex] == JsWriter.MapStartChar) { var tmpMap = ParseDictionary <TKey, TValue>(elementValue, createMapType, parseKeyFn, parseValueFn); if (tmpMap != null && tmpMap.Count > 0) { to[mapKey] = (TValue)tmpMap; } } else if (elementStartIndex < valueLength && value[elementStartIndex] == JsWriter.ListStartChar) { to[mapKey] = (TValue)DeserializeList <List <object>, TSerializer> .ParseStringSpan(elementValue); } else { to[mapKey] = (TValue)(tryToParseItemsAsPrimitiveTypes && elementStartIndex < valueLength ? DeserializeType <TSerializer> .ParsePrimitive(elementValue.Value(), value[elementStartIndex]) : parseValueFn(elementValue)); } } else { if (tryToParseItemsAsPrimitiveTypes && elementStartIndex < valueLength) { Serializer.EatWhitespace(value, ref elementStartIndex); to[mapKey] = (TValue)DeserializeType <TSerializer> .ParsePrimitive(elementValue.Value(), value[elementStartIndex]); } else { to[mapKey] = (TValue)parseValueFn(elementValue); } } Serializer.EatItemSeperatorOrMapEndChar(value, ref index); } return(to); }
public void SetUp() { LicenseUtils.RemoveLicense(); JsConfig.Reset(); }
public void TearDown() { JsConfig.Reset(); }
protected ServiceStackHost(string serviceName, params Assembly[] assembliesWithServices) { this.StartedAt = DateTime.UtcNow; ServiceName = serviceName; AppSettings = new AppSettings(); Container = new Container { DefaultOwner = Owner.External }; ServiceAssemblies = assembliesWithServices; ServiceController = CreateServiceController(assembliesWithServices); ContentTypes = Host.ContentTypes.Instance; RestPaths = new List <RestPath>(); Routes = new ServiceRoutes(this); Metadata = new ServiceMetadata(RestPaths); PreRequestFilters = new List <Action <IRequest, IResponse> >(); RequestConverters = new List <Func <IRequest, object, object> >(); ResponseConverters = new List <Func <IRequest, object, object> >(); GlobalRequestFilters = new List <Action <IRequest, IResponse, object> >(); GlobalTypedRequestFilters = new Dictionary <Type, ITypedFilter>(); GlobalResponseFilters = new List <Action <IRequest, IResponse, object> >(); GlobalTypedResponseFilters = new Dictionary <Type, ITypedFilter>(); GlobalMessageRequestFilters = new List <Action <IRequest, IResponse, object> >(); GlobalTypedMessageRequestFilters = new Dictionary <Type, ITypedFilter>(); GlobalMessageResponseFilters = new List <Action <IRequest, IResponse, object> >(); GlobalTypedMessageResponseFilters = new Dictionary <Type, ITypedFilter>(); GatewayRequestFilters = new List <Action <IRequest, object> >(); GatewayResponseFilters = new List <Action <IRequest, object> >(); ViewEngines = new List <IViewEngine>(); ServiceExceptionHandlers = new List <HandleServiceExceptionDelegate>(); UncaughtExceptionHandlers = new List <HandleUncaughtExceptionDelegate>(); AfterInitCallbacks = new List <Action <IAppHost> >(); OnDisposeCallbacks = new List <Action <IAppHost> >(); OnEndRequestCallbacks = new List <Action <IRequest> >(); RawHttpHandlers = new List <Func <IHttpRequest, IHttpHandler> > { HttpHandlerFactory.ReturnRequestInfo, MiniProfilerHandler.MatchesRequest, }; CatchAllHandlers = new List <HttpHandlerResolverDelegate>(); CustomErrorHttpHandlers = new Dictionary <HttpStatusCode, IServiceStackHandler> { { HttpStatusCode.Forbidden, new ForbiddenHttpHandler() }, { HttpStatusCode.NotFound, new NotFoundHttpHandler() }, }; StartUpErrors = new List <ResponseStatus>(); AsyncErrors = new List <ResponseStatus>(); PluginsLoaded = new List <string>(); Plugins = new List <IPlugin> { new HtmlFormat(), new CsvFormat(), new MarkdownFormat(), new PredefinedRoutesFeature(), new MetadataFeature(), new NativeTypesFeature(), new HttpCacheFeature(), }; ExcludeAutoRegisteringServiceTypes = new HashSet <Type> { typeof(AuthenticateService), typeof(RegisterService), typeof(AssignRolesService), typeof(UnAssignRolesService), typeof(NativeTypesService), typeof(PostmanService), }; JsConfig.InitStatics(); }
public void SetUp() { JsConfig.Reset(); }
public static void RegisterLicense(string licenseKeyText) { JsConfig.InitStatics(); if (__activatedLicense != null) //Skip multiple license registrations. Use RemoveLicense() to reset. { return; } string subId = null; var hold = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; try { if (IsFreeLicenseKey(licenseKeyText)) { ValidateFreeLicenseKey(licenseKeyText); return; } var parts = licenseKeyText.SplitOnFirst('-'); subId = parts[0]; if (int.TryParse(subId, out var subIdInt) && revokedSubs.Contains(subIdInt)) { throw new LicenseException("This subscription has been revoked. " + ContactDetails); } var key = VerifyLicenseKeyText(licenseKeyText); ValidateLicenseKey(key); } catch (PlatformNotSupportedException) { // Allow usage in environments like dotnet script __activatedLicense = new __ActivatedLicense(new LicenseKey { Type = LicenseType.Indie }); } catch (Exception ex) { //bubble unrelated project Exceptions switch (ex) { case FileNotFoundException or FileLoadException or BadImageFormatException or NotSupportedException #if NET6_0_OR_GREATER or System.Net.Http.HttpRequestException #endif or WebException or TaskCanceledException or LicenseException: throw; } var msg = "This license is invalid." + ContactDetails; if (!string.IsNullOrEmpty(subId)) { msg += $" The id for this license is '{subId}'"; } lock (typeof(LicenseUtils)) { try { var key = PclExport.Instance.VerifyLicenseKeyTextFallback(licenseKeyText); ValidateLicenseKey(key); } catch (Exception exFallback) { if (exFallback is FileNotFoundException or FileLoadException or BadImageFormatException) { throw; } throw new LicenseException(msg, exFallback).Trace(); } } throw new LicenseException(msg, ex).Trace(); } finally { Thread.CurrentThread.CurrentCulture = hold; } }
static QueryStringSerializer() { JsConfig.InitStatics(); Instance = new JsWriter <JsvTypeSerializer>(); }
internal static JsConfigScope GetJsScope() { return(JsConfig.With(new Config { ExcludeTypeInfo = false })); }
internal static object StringToType(ReadOnlySpan <char> strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair <string, TypeAccessor>[] typeAccessors) { var index = 0; var type = typeConfig.Type; if (strType.IsEmpty) { return(null); } var buffer = strType; var strTypeLength = strType.Length; //if (!Serializer.EatMapStartChar(strType, ref index)) for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline if (buffer[index] != JsWriter.MapStartChar) { throw DeserializeTypeRef.CreateSerializationError(type, strType.ToString()); } index++; if (JsonTypeSerializer.IsEmptyMap(strType, index)) { return(ctorFn()); } object instance = null; var lenient = JsConfig.PropertyConvention == PropertyConvention.Lenient; for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline while (index < strTypeLength) { var propertyName = JsonTypeSerializer.UnescapeJsString(strType, JsonUtils.QuoteChar, removeQuotes: true, ref index); //Serializer.EatMapKeySeperator(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline if (strTypeLength != index) { index++; } var propertyValueStr = Serializer.EatValue(strType, ref index); var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1; //if we already have an instance don't check type info, because then we will have a half deserialized object //we could throw here or just use the existing instance. if (instance == null && possibleTypeInfo && propertyName.Equals(typeAttr.Span, StringComparison.OrdinalIgnoreCase)) { var explicitTypeName = Serializer.ParseString(propertyValueStr); var explicitType = JsConfig.TypeFinder(explicitTypeName); if (explicitType == null || explicitType.IsInterface || explicitType.IsAbstract) { Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr.ToString()); } else if (!type.IsAssignableFrom(explicitType)) { Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr.ToString()); } else { JsWriter.AssertAllowedRuntimeType(explicitType); instance = explicitType.CreateInstance(); } if (instance != null) { //If __type info doesn't match, ignore it. if (!type.IsInstanceOfType(instance)) { instance = null; } else { var derivedType = instance.GetType(); if (derivedType != type) { var map = DeserializeTypeRef.GetCachedTypeAccessors(derivedType, Serializer); if (map != null) { typeAccessors = map; } } } } Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); continue; } if (instance == null) { instance = ctorFn(); } var typeAccessor = typeAccessors.Get(propertyName, lenient); var propType = possibleTypeInfo && propertyValueStr[0] == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr.ToString()) : null; if (propType != null) { try { if (typeAccessor != null) { //var parseFn = Serializer.GetParseFn(propType); var parseFn = JsonReader.GetParseStringSegmentFn(propType); var propertyValue = parseFn(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline if (index != strTypeLength) { var success = buffer[index] == JsWriter.ItemSeperator || buffer[index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline } } continue; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError(instance, propType, propertyName.ToString(), propertyValueStr.ToString(), e); } if (JsConfig.ThrowOnError) { throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), propType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString()); } } } if (typeAccessor?.GetProperty != null && typeAccessor.SetProperty != null) { try { var propertyValue = typeAccessor.GetProperty(propertyValueStr.ToString()); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } catch (NotSupportedException) { throw; } catch (Exception e) { if (JsConfig.OnDeserializationError != null) { JsConfig.OnDeserializationError(instance, propType ?? typeAccessor.PropertyType, propertyName.ToString(), propertyValueStr.ToString(), e); } if (JsConfig.ThrowOnError) { throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), typeAccessor.PropertyType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString()); } } } else { // the property is not known by the DTO typeConfig.OnDeserializing?.Invoke(instance, propertyName.ToString(), propertyValueStr.ToString()); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline if (index != strType.Length) { var success = buffer[index] == JsWriter.ItemSeperator || buffer[index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strTypeLength; index++) { if (!JsonUtils.IsWhiteSpace(buffer[index])) { break; } } //Whitespace inline } } } return(instance); }
public void SetUp() { OrmLiteConfig.ClearCache(); LicenseUtils.RemoveLicense(); JsConfig.Reset(); }
/// <summary> /// Writes to response. /// Response headers are customizable by implementing IHasOptions an returning Dictionary of Http headers. /// </summary> /// <param name="response">The response.</param> /// <param name="result">Whether or not it was implicitly handled by ServiceStack's built-in handlers.</param> /// <param name="defaultAction">The default action.</param> /// <param name="request">The serialization context.</param> /// <param name="bodyPrefix">Add prefix to response body if any</param> /// <param name="bodySuffix">Add suffix to response body if any</param> /// <returns></returns> public static async Task <bool> WriteToResponse(this IResponse response, object result, StreamSerializerDelegateAsync defaultAction, IRequest request, byte[] bodyPrefix, byte[] bodySuffix, CancellationToken token = default(CancellationToken)) { using (Profiler.Current.Step("Writing to Response")) { var defaultContentType = request.ResponseContentType; var disposableResult = result as IDisposable; bool flushAsync = false; try { if (result == null) { response.EndRequestWithNoContent(); return(true); } ApplyGlobalResponseHeaders(response); IDisposable resultScope = null; if (result is Exception) { if (response.Request.Items.TryGetValue(Keywords.ErrorView, out var oErrorView)) { response.Request.Items[Keywords.View] = oErrorView; } } var httpResult = result as IHttpResult; if (httpResult != null) { if (httpResult.ResultScope != null) { resultScope = httpResult.ResultScope(); } if (httpResult.RequestContext == null) { httpResult.RequestContext = request; } var paddingLength = bodyPrefix?.Length ?? 0; if (bodySuffix != null) { paddingLength += bodySuffix.Length; } httpResult.PaddingLength = paddingLength; if (httpResult is IHttpError httpError) { response.Dto = httpError.CreateErrorResponse(); if (await response.HandleCustomErrorHandler(request, defaultContentType, httpError.Status, response.Dto, httpError as Exception)) { return(true); } } response.Dto = response.Dto ?? httpResult.GetDto(); if (!response.HasStarted) { response.StatusCode = httpResult.Status; response.StatusDescription = (httpResult.StatusDescription ?? httpResult.StatusCode.ToString()).Localize(request); if (string.IsNullOrEmpty(httpResult.ContentType)) { httpResult.ContentType = defaultContentType; } response.ContentType = httpResult.ContentType; if (httpResult.Cookies != null) { foreach (var cookie in httpResult.Cookies) { response.SetCookie(cookie); } } } } else { response.Dto = result; } var config = HostContext.Config; if (!response.HasStarted) { /* Mono Error: Exception: Method not found: 'System.Web.HttpResponse.get_Headers' */ if (result is IHasOptions responseOptions) { //Reserving options with keys in the format 'xx.xxx' (No Http headers contain a '.' so its a safe restriction) const string reservedOptions = "."; foreach (var responseHeaders in responseOptions.Options) { if (responseHeaders.Key.Contains(reservedOptions)) { continue; } if (responseHeaders.Key == HttpHeaders.ContentLength) { response.SetContentLength(long.Parse(responseHeaders.Value)); continue; } if (responseHeaders.Key.EqualsIgnoreCase(HttpHeaders.ContentType)) { response.ContentType = responseHeaders.Value; continue; } if (Log.IsDebugEnabled) { Log.Debug($"Setting Custom HTTP Header: {responseHeaders.Key}: {responseHeaders.Value}"); } response.AddHeader(responseHeaders.Key, responseHeaders.Value); } } //ContentType='text/html' is the default for a HttpResponse //Do not override if another has been set if (response.ContentType == null || response.ContentType == MimeTypes.Html) { response.ContentType = defaultContentType == (config.DefaultContentType ?? MimeTypes.Html) && result is byte[] ? MimeTypes.Binary : defaultContentType; } if (bodyPrefix != null && response.ContentType.IndexOf(MimeTypes.Json, StringComparison.OrdinalIgnoreCase) >= 0) { response.ContentType = MimeTypes.JavaScript; } if (config.AppendUtf8CharsetOnContentTypes.Contains(response.ContentType)) { response.ContentType += ContentFormat.Utf8Suffix; } } var jsconfig = config.AllowJsConfig ? request.QueryString[Keywords.JsConfig] : null; using (resultScope) using (jsconfig != null ? JsConfig.CreateScope(jsconfig) : null) { if (WriteToOutputStream(response, result, bodyPrefix, bodySuffix)) { response.Flush(); //required for Compression return(true); } #if NET45 //JsConfigScope uses ThreadStatic in .NET v4.5 so avoid async thread hops by writing sync to MemoryStream if (resultScope != null || jsconfig != null) { response.UseBufferedStream = true; } #endif if (await WriteToOutputStreamAsync(response, result, bodyPrefix, bodySuffix, token)) { flushAsync = true; return(true); } if (httpResult != null) { result = httpResult.Response; } if (result is string responseText) { var strBytes = responseText.ToUtf8Bytes(); var len = (bodyPrefix?.Length).GetValueOrDefault() + strBytes.Length + (bodySuffix?.Length).GetValueOrDefault(); response.SetContentLength(len); if (response.ContentType == null || response.ContentType == MimeTypes.Html) { response.ContentType = defaultContentType; } //retain behavior with ASP.NET's response.Write(string) if (response.ContentType.IndexOf(';') == -1) { response.ContentType += ContentFormat.Utf8Suffix; } if (bodyPrefix != null) { await response.OutputStream.WriteAsync(bodyPrefix, token); } await response.OutputStream.WriteAsync(strBytes, token); if (bodySuffix != null) { await response.OutputStream.WriteAsync(bodySuffix, token); } return(true); } if (defaultAction == null) { throw new ArgumentNullException(nameof(defaultAction), $"As result '{(result != null ? result.GetType().GetOperationName() : "")}' is not a supported responseType, a defaultAction must be supplied"); } if (bodyPrefix != null) { await response.OutputStream.WriteAsync(bodyPrefix, token); } if (result != null) { await defaultAction(request, result, response.OutputStream); } if (bodySuffix != null) { await response.OutputStream.WriteAsync(bodySuffix, token); } } return(false); } catch (Exception originalEx) { //.NET Core prohibits some status codes from having a body if (originalEx is InvalidOperationException invalidEx) { Log.Error(invalidEx.Message, invalidEx); await response.OutputStream.FlushAsync(token); // Prevent hanging clients } await HandleResponseWriteException(originalEx, request, response, defaultContentType); return(true); } finally { if (flushAsync) // move async Thread Hop to outside JsConfigScope so .NET v4.5 disposes same scope { try { await response.FlushAsync(token); } catch (Exception flushEx) { Log.Error("response.FlushAsync()", flushEx); } } disposableResult?.Dispose(); await response.EndRequestAsync(skipHeaders : true); } } }
private ParseStringSpanDelegate GetCoreParseStringSpanFn <T>() { var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); if (JsConfig <T> .HasDeserializeFn) { return(value => JsConfig <T> .ParseFn(Serializer, value.Value())); } if (type.IsEnum) { return(x => ParseUtils.TryParseEnum(type, Serializer.UnescapeSafeString(x).Value())); } if (type == typeof(string)) { return(Serializer.UnescapeStringAsObject); } if (type == typeof(object)) { return(DeserializeType <TSerializer> .ObjectStringToType); } var specialParseFn = ParseUtils.GetSpecialParseMethod(type); if (specialParseFn != null) { return(v => specialParseFn(v.Value())); } if (type.IsArray) { return(DeserializeArray <T, TSerializer> .ParseStringSpan); } var builtInMethod = DeserializeBuiltin <T> .ParseStringSpan; if (builtInMethod != null) { return(value => builtInMethod(Serializer.UnescapeSafeString(value))); } if (type.HasGenericType()) { if (type.IsOrHasGenericInterfaceTypeOf(typeof(IList <>))) { return(DeserializeList <T, TSerializer> .ParseStringSpan); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IDictionary <,>))) { return(DeserializeDictionary <TSerializer> .GetParseStringSegmentMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(ICollection <>))) { return(DeserializeCollection <TSerializer> .GetParseStringSegmentMethod(type)); } if (type.HasAnyTypeDefinitionsOf(typeof(Queue <>)) || type.HasAnyTypeDefinitionsOf(typeof(Stack <>))) { return(DeserializeSpecializedCollections <T, TSerializer> .ParseStringSpan); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(KeyValuePair <,>))) { return(DeserializeKeyValuePair <TSerializer> .GetParseStringSegmentMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IEnumerable <>))) { return(DeserializeEnumerable <T, TSerializer> .ParseStringSpan); } var customFn = DeserializeCustomGenericType <TSerializer> .GetParseStringSegmentMethod(type); if (customFn != null) { return(customFn); } } var pclParseFn = PclExport.Instance.GetJsReaderParseStringSpanMethod <TSerializer>(typeof(T)); if (pclParseFn != null) { return(pclParseFn); } var isDictionary = typeof(T) != typeof(IEnumerable) && typeof(T) != typeof(ICollection) && (typeof(T).IsAssignableFrom(typeof(IDictionary)) || typeof(T).HasInterface(typeof(IDictionary))); if (isDictionary) { return(DeserializeDictionary <TSerializer> .GetParseStringSegmentMethod(type)); } var isEnumerable = typeof(T).IsAssignableFrom(typeof(IEnumerable)) || typeof(T).HasInterface(typeof(IEnumerable)); if (isEnumerable) { var parseFn = DeserializeSpecializedCollections <T, TSerializer> .ParseStringSpan; if (parseFn != null) { return(parseFn); } } if (type.IsValueType) { //at first try to find more faster `ParseStringSegment` method var staticParseStringSegmentMethod = StaticParseMethod <T> .ParseStringSpan; if (staticParseStringSegmentMethod != null) { return(value => staticParseStringSegmentMethod(Serializer.UnescapeSafeString(value))); } //then try to find `Parse` method var staticParseMethod = StaticParseMethod <T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value).ToString())); } } else { var staticParseStringSegmentMethod = StaticParseRefTypeMethod <TSerializer, T> .ParseStringSpan; if (staticParseStringSegmentMethod != null) { return(value => staticParseStringSegmentMethod(Serializer.UnescapeSafeString(value))); } var staticParseMethod = StaticParseRefTypeMethod <TSerializer, T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value).ToString())); } } var typeConstructor = DeserializeType <TSerializer> .GetParseStringSpanMethod(TypeConfig <T> .GetState()); if (typeConstructor != null) { return(typeConstructor); } var stringConstructor = DeserializeTypeUtils.GetParseStringSegmentMethod(type); if (stringConstructor != null) { return(stringConstructor); } return(DeserializeType <TSerializer> .ParseAbstractType <T>); }