public void Does_preserve_UTC_timezone_with_all_fractions(string dateFmt) { using var scope = JsConfig.CreateScope("AssumeUtc:false,AlwaysUseUtc:true,SkipDateTimeConversion:true"); var date = JsonSerializer.DeserializeFromString <DateTime>(dateFmt); Assert.That(date.Kind, Is.EqualTo(DateTimeKind.Utc)); Assert.That(date, Is.EqualTo(new DateTime(2020, 08, 07, 9, 36, 20)) .Within(TimeSpan.FromSeconds(1))); }
public void Does_create_scope_from_string_using_CamelCaseHumps() { var scope = JsConfig.CreateScope("eccn,elun,inv:false,edv:0,ide:1"); Assert.That(scope.EmitCamelCaseNames); Assert.That(scope.EmitLowercaseUnderscoreNames); Assert.That(!scope.IncludeNullValues); Assert.That(!scope.ExcludeDefaultValues); Assert.That(scope.IncludeDefaultEnums); scope.Dispose(); scope = JsConfig.CreateScope("dh:ISO8601,tsh:df,pc:strict"); Assert.That(scope.DateHandler, Is.EqualTo(DateHandler.ISO8601)); Assert.That(scope.TimeSpanHandler, Is.EqualTo(TimeSpanHandler.DurationFormat)); Assert.That(scope.PropertyConvention, Is.EqualTo(PropertyConvention.Strict)); scope.Dispose(); }
public void Does_create_scope_from_string() { var scope = JsConfig.CreateScope("EmitCamelCaseNames,emitlowercaseunderscorenames,IncludeNullValues:false,ExcludeDefaultValues:0,IncludeDefaultEnums:1"); Assert.That(scope.EmitCamelCaseNames); Assert.That(scope.EmitLowercaseUnderscoreNames); Assert.That(!scope.IncludeNullValues); Assert.That(!scope.ExcludeDefaultValues); Assert.That(scope.IncludeDefaultEnums); scope.Dispose(); scope = JsConfig.CreateScope("DateHandler:ISO8601,timespanhandler:durationformat,PropertyConvention:strict"); Assert.That(scope.DateHandler, Is.EqualTo(DateHandler.ISO8601)); Assert.That(scope.TimeSpanHandler, Is.EqualTo(TimeSpanHandler.DurationFormat)); Assert.That(scope.PropertyConvention, Is.EqualTo(PropertyConvention.Strict)); scope.Dispose(); }
public string ToJson(Pass pass) { var properties = pass.GetType().GetProperties(); var jsonDict = new Dictionary <object, object>(); Func <string, bool> isIgnoredField = value => new List <string> { "type", "localizations" }.Contains(value); Func <object, bool> isNull = value => value == null; Func <object, bool> isAsset = value => value.GetType() == typeof(Asset); Func <object, bool> isEmptyList = value => value is IList && ((IList)value).Count == 0; foreach (var property in properties) { string name = property.Name; object value = property.GetValue(pass); if (name.Equals("fields")) { var fields = ((Dictionary <FieldType, List <Field> >)value) .ToDictionary(x => SerializeFieldType(x.Key), x => x.Value); jsonDict.Add(pass.type, fields); } else if (isIgnoredField(name) || isNull(value) || isAsset(value) || isEmptyList(value)) { // don't include value } else { jsonDict.Add(name, value); } } string json = null; using (var config = JsConfig.CreateScope("ExcludeTypeInfo")) { JsConfig.DateHandler = DateHandler.ISO8601; json = jsonDict.ToJson(); } return(json); }
/// <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; } ReadOnlyMemory <byte>?uf8Bytes = null; if (result is string responseText) { uf8Bytes = MemoryProvider.Instance.ToUtf8(responseText.AsSpan()); } else if (result is ReadOnlyMemory <char> rom) { uf8Bytes = MemoryProvider.Instance.ToUtf8(rom.Span); } if (uf8Bytes != null) { var len = (bodyPrefix?.Length).GetValueOrDefault() + uf8Bytes.Value.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(uf8Bytes.Value, 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); } } }
/// <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 implicity 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 Task <bool> WriteToResponse(this IResponse response, object result, ResponseSerializerDelegate defaultAction, IRequest request, byte[] bodyPrefix, byte[] bodySuffix) { using (Profiler.Current.Step("Writing to Response")) { var defaultContentType = request.ResponseContentType; try { if (result == null) { response.EndRequestWithNoContent(); return(TypeConstants.TrueTask); } ApplyGlobalResponseHeaders(response); IDisposable resultScope = null; 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; var httpError = httpResult as IHttpError; if (httpError != null) { response.Dto = httpError.CreateErrorResponse(); if (response.HandleCustomErrorHandler(request, defaultContentType, httpError.Status, response.Dto)) { return(TypeConstants.TrueTask); } } response.Dto = response.Dto ?? httpResult.GetDto(); 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; } /* Mono Error: Exception: Method not found: 'System.Web.HttpResponse.get_Headers' */ var responseOptions = result as IHasOptions; if (responseOptions != null) { //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 (Log.IsDebugEnabled) { Log.Debug($"Setting Custom HTTP Header: {responseHeaders.Key}: {responseHeaders.Value}"); } if (Env.IsMono && responseHeaders.Key.EqualsIgnoreCase(HttpHeaders.ContentType)) { response.ContentType = responseHeaders.Value; } else { 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; } if (bodyPrefix != null && response.ContentType.IndexOf(MimeTypes.Json, StringComparison.OrdinalIgnoreCase) >= 0) { response.ContentType = MimeTypes.JavaScript; } if (HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(response.ContentType)) { response.ContentType += ContentFormat.Utf8Suffix; } using (resultScope) using (HostContext.Config.AllowJsConfig ? JsConfig.CreateScope(request.QueryString[Keywords.JsConfig]) : null) { var disposableResult = result as IDisposable; if (WriteToOutputStream(response, result, bodyPrefix, bodySuffix)) { response.Flush(); //required for Compression disposableResult?.Dispose(); return(TypeConstants.TrueTask); } if (httpResult != null) { result = httpResult.Response; } var responseText = result as string; if (responseText != null) { if (bodyPrefix != null) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } if (response.ContentType == null || response.ContentType == MimeTypes.Html) { response.ContentType = defaultContentType; } response.Write(responseText); if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } return(TypeConstants.TrueTask); } 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) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } if (result != null) { defaultAction(request, result, response); } if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } disposableResult?.Dispose(); } return(TypeConstants.FalseTask); } catch (Exception originalEx) { return(HandleResponseWriteException(originalEx, request, response, defaultContentType)); } finally { response.EndRequest(skipHeaders: true); } } }
private async Task <bool> CacheAndWriteResponse(CacheInfo cacheInfo, IRequest req, IResponse res, object response) { var httpResult = response as IHttpResult; var dto = httpResult != null ? httpResult.Response : response; if (dto == null || dto is IPartialWriter || dto is IPartialWriterAsync || dto is IStreamWriter || dto is IStreamWriterAsync) { return(false); } var expiresIn = cacheInfo.ExpiresIn.GetValueOrDefault(DefaultExpiresIn); var cache = cacheInfo.LocalCache ? HostContext.AppHost.GetMemoryCacheClient(req) : HostContext.AppHost.GetCacheClient(req); var responseBytes = dto as byte[]; if (responseBytes == null) { if (dto is string rawStr) { responseBytes = rawStr.ToUtf8Bytes(); } else { if (dto is Stream stream) { responseBytes = stream.ReadFully(); } } } var encoding = !cacheInfo.NoCompression ? req.GetCompressionType() : null; if (response is HttpResult customResult) { if (customResult.View != null) { req.Items[Keywords.View] = customResult.View; } if (customResult.Template != null) { req.Items[Keywords.Template] = customResult.Template; } } using (httpResult?.ResultScope?.Invoke()) using (HostContext.Config.AllowJsConfig ? JsConfig.CreateScope(req.QueryString[Keywords.JsConfig]) : null) { var cacheKeyEncoded = encoding != null ? cacheInfo.CacheKey + "." + encoding : null; if (responseBytes != null || req.ResponseContentType.IsBinary()) { if (responseBytes == null) { responseBytes = HostContext.ContentTypes.SerializeToBytes(req, dto); } cache.Set(cacheInfo.CacheKey, responseBytes, expiresIn); if (encoding != null) { res.AddHeader(HttpHeaders.ContentEncoding, encoding); responseBytes = responseBytes.CompressBytes(encoding); cache.Set(cacheKeyEncoded, responseBytes, expiresIn); } } else { var serializedDto = req.SerializeToString(dto); if (req.ResponseContentType.MatchesContentType(MimeTypes.Json)) { var jsonp = req.GetJsonpCallback(); if (jsonp != null) { serializedDto = jsonp + "(" + serializedDto + ")"; } } responseBytes = serializedDto.ToUtf8Bytes(); cache.Set(cacheInfo.CacheKey, responseBytes, expiresIn); if (encoding != null) { res.AddHeader(HttpHeaders.ContentEncoding, encoding); responseBytes = responseBytes.CompressBytes(encoding); cache.Set(cacheKeyEncoded, responseBytes, expiresIn); } } } var doHttpCaching = cacheInfo.MaxAge != null || cacheInfo.CacheControl != CacheControl.None; if (doHttpCaching) { var cacheControl = BuildCacheControlHeader(cacheInfo); if (cacheControl != null) { var lastModified = cacheInfo.LastModified.GetValueOrDefault(DateTime.UtcNow); cache.Set("date:" + cacheInfo.CacheKey, lastModified, expiresIn); res.AddHeaderLastModified(lastModified); res.AddHeader(HttpHeaders.CacheControl, cacheControl); if (encoding != null) { res.AddHeader(HttpHeaders.Vary, "Accept-Encoding"); } if (cacheInfo.VaryByUser) { res.AddHeader(HttpHeaders.Vary, "Cookie"); } } } if (httpResult != null) { foreach (var header in httpResult.Headers) { res.AddHeader(header.Key, header.Value); } } await res.WriteBytesToResponse(responseBytes, req.ResponseContentType); return(true); }
public static async Task WriteErrorToResponse(this IResponse httpRes, IRequest httpReq, string contentType, string operationName, string errorMessage, Exception ex, int statusCode) { if (ex == null) { ex = new Exception(errorMessage); } httpRes.Dto = HostContext.AppHost.CreateErrorResponse(ex, request: httpReq?.Dto); if (await HandleCustomErrorHandler(httpRes, httpReq, contentType, statusCode, httpRes.Dto, ex)) { return; } var hostConfig = HostContext.Config; if (!httpRes.HasStarted) { if ((httpRes.ContentType == null || httpRes.ContentType == MimeTypes.Html) && contentType != null && contentType != httpRes.ContentType) { httpRes.ContentType = contentType; } if (hostConfig.AppendUtf8CharsetOnContentTypes.Contains(contentType)) { httpRes.ContentType += ContentFormat.Utf8Suffix; } var hold = httpRes.StatusDescription; var hasDefaultStatusDescription = hold is null or "OK"; httpRes.StatusCode = statusCode; httpRes.StatusDescription = hasDefaultStatusDescription ? (errorMessage ?? HttpStatus.GetStatusDescription(statusCode)) : hold; httpRes.ApplyGlobalResponseHeaders(); } var callback = httpReq.GetJsonpCallback(); var doJsonp = hostConfig.AllowJsonpRequests && !string.IsNullOrEmpty(callback); if (doJsonp) { httpRes.StatusCode = 200; await httpRes.OutputStream.WriteAsync(DataCache.CreateJsonpPrefix(callback)); } var serializer = HostContext.ContentTypes.GetStreamSerializerAsync(contentType ?? httpRes.ContentType); if (serializer != null) { var jsconfig = hostConfig.AllowJsConfig ? httpReq?.QueryString[Keywords.JsConfig] : null; using (jsconfig != null ? JsConfig.CreateScope(jsconfig) : null) { await serializer(httpReq, httpRes.Dto, httpRes.OutputStream); } } if (doJsonp) { await httpRes.OutputStream.WriteAsync(DataCache.JsonpSuffix); } httpRes.EndHttpHandlerRequest(skipHeaders: true); }
/// <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 implicity 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 Task <bool> WriteToResponse(this IResponse response, object result, ResponseSerializerDelegate defaultAction, IRequest request, byte[] bodyPrefix, byte[] bodySuffix) { using (Profiler.Current.Step("Writing to Response")) { var defaultContentType = request.ResponseContentType; try { if (result == null) { response.EndRequestWithNoContent(); return(TrueTask); } ApplyGlobalResponseHeaders(response); IDisposable resultScope = null; 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 != null ? bodyPrefix.Length : 0; if (bodySuffix != null) { paddingLength += bodySuffix.Length; } httpResult.PaddingLength = paddingLength; var httpError = httpResult as IHttpError; if (httpError != null) { response.Dto = httpError.CreateErrorResponse(); if (response.HandleCustomErrorHandler(request, defaultContentType, httpError.Status, response.Dto)) { return(TrueTask); } } response.Dto = response.Dto ?? httpResult.GetDto(); 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; } /* Mono Error: Exception: Method not found: 'System.Web.HttpResponse.get_Headers' */ var responseOptions = result as IHasOptions; if (responseOptions != null) { //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 (Log.IsDebugEnabled) { Log.DebugFormat("Setting Custom HTTP Header: {0}: {1}", responseHeaders.Key, responseHeaders.Value); } if (Env.IsMono && responseHeaders.Key.EqualsIgnoreCase(HttpHeaders.ContentType)) { response.ContentType = responseHeaders.Value; } else { 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; } if (bodyPrefix != null && response.ContentType.IndexOf(MimeTypes.Json, StringComparison.InvariantCultureIgnoreCase) >= 0) { response.ContentType = MimeTypes.JavaScript; } if (HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(response.ContentType)) { response.ContentType += ContentFormat.Utf8Suffix; } using (resultScope) using (JsConfig.CreateScope(request.QueryString[Keywords.JsConfig])) { var disposableResult = result as IDisposable; if (WriteToOutputStream(response, result, bodyPrefix, bodySuffix)) { response.Flush(); //required for Compression if (disposableResult != null) { disposableResult.Dispose(); } return(TrueTask); } if (httpResult != null) { result = httpResult.Response; } var responseText = result as string; if (responseText != null) { if (bodyPrefix != null) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } WriteTextToResponse(response, responseText, defaultContentType); if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } return(TrueTask); } if (defaultAction == null) { throw new ArgumentNullException("defaultAction", String.Format( "As result '{0}' is not a supported responseType, a defaultAction must be supplied", (result != null ? result.GetType().GetOperationName() : ""))); } if (bodyPrefix != null) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } if (result != null) { defaultAction(request, result, response); } if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } if (disposableResult != null) { disposableResult.Dispose(); } } return(FalseTask); } catch (Exception originalEx) { HostContext.RaiseAndHandleUncaughtException(request, response, request.OperationName, originalEx); if (!HostContext.Config.WriteErrorsToResponse) { return(originalEx.AsTaskException <bool>()); } var errorMessage = String.Format( "Error occured while Processing Request: [{0}] {1}", originalEx.GetType().GetOperationName(), originalEx.Message); try { if (!response.IsClosed) { response.WriteErrorToResponse( request, defaultContentType, request.OperationName, errorMessage, originalEx, (int)HttpStatusCode.InternalServerError); } } catch (Exception writeErrorEx) { //Exception in writing to response should not hide the original exception Log.Info("Failed to write error to response: {0}", writeErrorEx); return(originalEx.AsTaskException <bool>()); } return(TrueTask); } finally { response.EndRequest(skipHeaders: true); } } }