public async Task<bool> ProcessRequest(HttpContext httpContext)
{
options.Logger.ProcessRequestStart(httpContext.Request.Path);
MemoryStream bufferedRequestStream = null;
var originalRequestStream = httpContext.Request.Body;
if (!originalRequestStream.CanSeek)
{
bufferedRequestStream = new MemoryStream();
if (options.StreamWriteOption == StreamWriteOption.BufferAndAsynchronousWrite)
{
await originalRequestStream.CopyToAsync(bufferedRequestStream); // keep context
}
else
{
originalRequestStream.CopyTo(bufferedRequestStream);
}
bufferedRequestStream.Position = 0;
httpContext.Request.Body = bufferedRequestStream;
}
try
{
var coordinator = options.OperationCoordinatorFactory.Create();
if (!coordinator.OnStartProcessRequest(options, httpContext))
{
return ReturnNextMiddleware(httpContext);
}
AcceptVerbs verb;
string ext;
var handler = SelectHandler(httpContext, coordinator, out verb, out ext);
if (handler == null) return ReturnNextMiddleware(httpContext);
// Parameter binding
var valueProvider = new ValueProvider(httpContext, verb);
var methodParameters = ParameterBinder.BindParameter(httpContext, options, coordinator, valueProvider, handler.Arguments);
if (methodParameters == null) return ReturnNextMiddleware(httpContext);
// select formatter
var formatter = handler.NegotiateFormat(httpContext, ext, options, coordinator);
if (formatter == null)
{
if (formatter == null) return ReturnNextMiddleware(httpContext);
}
try
{
// Operation execute
var context = new OperationContext(httpContext, handler.ClassName, handler.MethodName, verb)
{
Parameters = methodParameters,
ParameterNames = handler.ParameterNames,
ContentFormatter = formatter,
Attributes = handler.AttributeLookup
};
var executionPath = context.ToString();
options.Logger.ExecuteStart(executionPath);
var sw = Stopwatch.StartNew();
var interrupted = false;
try
{
await handler.Execute(options, context, coordinator).ConfigureAwait(false);
}
catch
{
interrupted = true;
throw;
}
finally
{
sw.Stop();
options.Logger.ExecuteFinished(executionPath, interrupted, sw.Elapsed.TotalMilliseconds);
}
return ReturnNextMiddleware(httpContext);
}
catch (ReturnStatusCodeException statusException)
{
try
{
if (options.UseOtherMiddleware && options.PassThroughWhenStatusCodesAre != null)
{
var code = (int)statusException.StatusCode;
for (int i = 0; i < options.PassThroughWhenStatusCodesAre.Length; i++)
{
if (code == (int)options.PassThroughWhenStatusCodesAre[i])
{
httpContext.Response.StatusCode = code;
return ReturnNextMiddleware(httpContext);
}
}
}
statusException.EmitCode(options, httpContext);
}
catch (Exception ex)
{
if (IsRethrowOrEmitException(coordinator, options, httpContext, ex))
{
throw;
}
}
}
catch (Exception ex)
{
if (IsRethrowOrEmitException(coordinator, options, httpContext, ex))
{
throw;
}
}
}
finally
{
if (bufferedRequestStream != null)
{
bufferedRequestStream.Dispose();
}
httpContext.Request.Body = originalRequestStream;
}
return ReturnNextMiddleware(httpContext);
}