internal static object[] BindParameter(HttpContext httpContext, ILightNodeOptions options, IOperationCoordinator coordinator, ValueProvider valueProvider, ParameterInfoSlim[] arguments) { var methodParameters = new object[arguments.Length]; for (int i = 0; i < arguments.Length; i++) { var item = arguments[i]; var _values = valueProvider.GetValue(item.Name); var value = _values as string; var values = _values as List <string>; var isEmpty = _values == null; if (isEmpty && !item.ParameterTypeIsArray) { if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { coordinator.OnProcessInterrupt(options, httpContext, InterruptReason.ParameterBindMissing, "Lack of Parameter:" + item.Name); options.Logger.ParameterBindMissing(OperationMissingKind.LackOfParameter, item.Name); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ThrowException) { throw new ParameterMissingException(OperationMissingKind.LackOfParameter, item.Name); } else { httpContext.EmitBadRequest(); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ReturnErrorStatusCodeIncludeErrorDetails) { httpContext.EmitStringMessage("Lack of Parameter:" + item.Name); } return(null); } } } else if (!item.ParameterTypeIsArray) { var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (conv == null) { throw new InvalidOperationException("critical:register code is broken"); } object pValue; if (conv(value ?? values[0], out pValue)) { methodParameters[i] = pValue; continue; } else if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { coordinator.OnProcessInterrupt(options, httpContext, InterruptReason.ParameterBindMissing, "Mismatch ParameterType:" + item.Name); options.Logger.ParameterBindMissing(OperationMissingKind.MissmatchParameterType, item.Name); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ThrowException) { throw new ParameterMissingException(OperationMissingKind.MissmatchParameterType, item.Name); } else { httpContext.EmitBadRequest(); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ReturnErrorStatusCodeIncludeErrorDetails) { httpContext.EmitStringMessage("Mismatch ParameterType:" + item.Name); } return(null); } } } var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (arrayConv == null) { throw new InvalidOperationException("critical:register code is broken"); } methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : (IList <string>) new string[0]); continue; } return(methodParameters); }
internal static object[] BindParameter(IDictionary<string, object> environment, ILightNodeOptions options, IOperationCoordinator coordinator, ValueProvider valueProvider, ParameterInfoSlim[] arguments) { var methodParameters = new object[arguments.Length]; for (int i = 0; i < arguments.Length; i++) { var item = arguments[i]; var _values = valueProvider.GetValue(item.Name); var value = _values as string; var values = _values as List<string>; var isEmpty = _values == null; var byteArray = _values as byte[]; // TODO:Experimental support if (byteArray != null && item.ParameterTypeIsArray && item.ParameterType == typeof(byte[])) { methodParameters[i] = byteArray; continue; } if (isEmpty && !item.ParameterTypeIsArray) { if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { coordinator.OnProcessInterrupt(options, environment, InterruptReason.ParameterBindMissing, "Lack of Parameter:" + item.Name); options.Logger.ParameterBindMissing(OperationMissingKind.LackOfParameter, item.Name); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ThrowException) { throw new ParameterMissingException(OperationMissingKind.LackOfParameter, item.Name); } else { environment.EmitBadRequest(); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ReturnErrorStatusCodeIncludeErrorDetails) { environment.EmitStringMessage("Lack of Parameter:" + item.Name); } return null; } } } else if (!item.ParameterTypeIsArray) { var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (conv == null) throw new InvalidOperationException("critical:register code is broken"); object pValue; if (conv(value ?? values[0], out pValue)) { methodParameters[i] = pValue; continue; } else if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { coordinator.OnProcessInterrupt(options, environment, InterruptReason.ParameterBindMissing, "Mismatch ParameterType:" + item.Name); options.Logger.ParameterBindMissing(OperationMissingKind.MissmatchParameterType, item.Name); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ThrowException) { throw new ParameterMissingException(OperationMissingKind.MissmatchParameterType, item.Name); } else { environment.EmitBadRequest(); if (options.OperationMissingHandlingPolicy == OperationMissingHandlingPolicy.ReturnErrorStatusCodeIncludeErrorDetails) { environment.EmitStringMessage("Mismatch ParameterType:" + item.Name); } return null; } } } var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (arrayConv == null) throw new InvalidOperationException("critical:register code is broken"); methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : (IList<string>)new string[0]); continue; } return methodParameters; }
// Routing -> ParameterBinding -> Execute public async Task<bool> ProcessRequest(IDictionary<string, object> environment) { options.Logger.ProcessRequestStart(environment.AsRequestPath()); MemoryStream bufferedRequestStream = null; var originalRequestStream = environment.AsRequestBody(); if (!originalRequestStream.CanSeek) { bufferedRequestStream = new MemoryStream(); if (options.StreamWriteOption == StreamWriteOption.BufferAndAsynchronousWrite) { await originalRequestStream.CopyToAsync(bufferedRequestStream); // keep context } else { originalRequestStream.CopyTo(bufferedRequestStream); } bufferedRequestStream.Position = 0; environment[OwinConstants.RequestBody] = bufferedRequestStream; } try { var coordinator = options.OperationCoordinatorFactory.Create(); if (!coordinator.OnStartProcessRequest(options, environment)) { return ReturnNextMiddleware(environment); } AcceptVerbs verb; string ext; var handler = SelectHandler(environment, coordinator, out verb, out ext); if (handler == null) return ReturnNextMiddleware(environment); // Parameter binding var valueProvider = new ValueProvider(environment, verb); var methodParameters = ParameterBinder.BindParameter(environment, options, coordinator, valueProvider, handler.Arguments); if (methodParameters == null) return ReturnNextMiddleware(environment); // select formatter var formatter = handler.NegotiateFormat(environment, ext, options, coordinator); if (formatter == null) { if (formatter == null) return ReturnNextMiddleware(environment); } try { // Operation execute var context = new OperationContext(environment, 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(environment); } 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 == options.PassThroughWhenStatusCodesAre[i]) { environment[OwinConstants.ResponseStatusCode] = code; // emit only code. return ReturnNextMiddleware(environment); } } } statusException.EmitCode(options, environment); } catch (Exception ex) { if (IsRethrowOrEmitException(coordinator, options, environment, ex)) { throw; } } } catch (Exception ex) { if (IsRethrowOrEmitException(coordinator, options, environment, ex)) { throw; } } } finally { if (bufferedRequestStream != null) { bufferedRequestStream.Dispose(); } environment[OwinConstants.RequestBody] = originalRequestStream; } return ReturnNextMiddleware(environment); }
// Routing -> ParameterBinding -> Execute public async Task ProcessRequest(IDictionary <string, object> environment) { options.Logger.ProcessRequestStart(environment.AsRequestPath()); MemoryStream bufferedRequestStream = null; var originalRequestStream = environment.AsRequestBody(); if (!originalRequestStream.CanSeek) { bufferedRequestStream = new MemoryStream(); if (options.StreamWriteOption == StreamWriteOption.BufferAndAsynchronousWrite) { await originalRequestStream.CopyToAsync(bufferedRequestStream); // keep context } else { originalRequestStream.CopyTo(bufferedRequestStream); } bufferedRequestStream.Position = 0; environment[OwinConstants.RequestBody] = bufferedRequestStream; } try { var coordinator = options.OperationCoordinatorFactory.Create(); if (!coordinator.OnStartProcessRequest(options, environment)) { return; } AcceptVerbs verb; string ext; var handler = SelectHandler(environment, coordinator, out verb, out ext); if (handler == null) { return; } // Parameter binding var valueProvider = new ValueProvider(environment, verb); var methodParameters = ParameterBinder.BindParameter(environment, options, coordinator, valueProvider, handler.Arguments); if (methodParameters == null) { return; } // select formatter var formatter = handler.NegotiateFormat(environment, ext, options, coordinator); if (formatter == null) { if (formatter == null) { return; } } try { // Operation execute var context = new OperationContext(environment, 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; } catch (ReturnStatusCodeException statusException) { try { statusException.EmitCode(options, environment); } catch (Exception ex) { if (IsRethrowOrEmitException(coordinator, options, environment, ex)) { throw; } } } catch (Exception ex) { if (IsRethrowOrEmitException(coordinator, options, environment, ex)) { throw; } } } finally { if (bufferedRequestStream != null) { bufferedRequestStream.Dispose(); } environment[OwinConstants.RequestBody] = originalRequestStream; } }
// Routing -> ParameterBinding -> Execute 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 == options.PassThroughWhenStatusCodesAre[i]) { httpContext.Response.StatusCode = code; // emit only 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)); }
// Routing -> ParameterBinding -> Execute public async Task ProcessRequest(IDictionary<string, object> environment) { try { AcceptVerbs verb; string ext; var handler = SelectHandler(environment, out verb, out ext); if (handler == null) return; // verb check | TODO:check operation verb attribute if (!options.DefaultAcceptVerb.HasFlag(verb)) { environment.EmitMethodNotAllowed(); return; } // Parameter binding var valueProvider = new ValueProvider(environment, verb); var methodParameters = ParameterBinder.BindParameter(environment, options, valueProvider, handler.Arguments); if (methodParameters == null) return; // select formatter var formatter = NegotiateFormat(environment, ext); if (formatter == null) return; // Operation execute var context = new OperationContext(environment, handler.ClassName, handler.MethodName, verb) { Parameters = methodParameters, ContentFormatter = formatter, Attributes = handler.AttributeLookup }; await handler.Execute(options, context).ConfigureAwait(false); return; } catch (ReturnStatusCodeException statusException) { statusException.EmitCode(environment); return; } catch (Exception ex) { switch (options.ErrorHandlingPolicy) { case ErrorHandlingPolicy.ReturnInternalServerError: environment.EmitInternalServerError(); return; case ErrorHandlingPolicy.ReturnInternalServerErrorIncludeErrorDetails: environment.EmitInternalServerError(); environment.EmitStringMessage(ex.ToString()); return; case ErrorHandlingPolicy.ThrowException: default: throw; } } }
internal static object[] BindParameter(IDictionary<string, object> environment, LightNodeOptions options, ValueProvider valueProvider, ParameterInfoSlim[] arguments) { var methodParameters = new object[arguments.Length]; for (int i = 0; i < arguments.Length; i++) { var item = arguments[i]; var _values = valueProvider.GetValue(item.Name); var value = _values as string; var values = _values as List<string>; var isEmpty = _values == null; if (isEmpty && !item.ParameterTypeIsArray) { if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { environment.EmitBadRequest(); environment.EmitStringMessage("Lack of Parameter:" + item.Name); return null; } } else if (!item.ParameterTypeIsArray) { var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (conv == null) throw new InvalidOperationException("critical:register code is broken"); object pValue; if (conv(value ?? values[0], out pValue)) { methodParameters[i] = pValue; continue; } else if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { environment.EmitBadRequest(); environment.EmitStringMessage("Mismatch Parameter Type:" + item.Name); return null; } } var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (arrayConv == null) throw new InvalidOperationException("critical:register code is broken"); methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : Enumerable.Empty<string>()); continue; } return methodParameters; }
internal static object[] BindParameter(IDictionary <string, object> environment, LightNodeOptions options, ValueProvider valueProvider, ParameterInfoSlim[] arguments) { var methodParameters = new object[arguments.Length]; for (int i = 0; i < arguments.Length; i++) { var item = arguments[i]; var _values = valueProvider.GetValue(item.Name); var value = _values as string; var values = _values as List <string>; var isEmpty = _values == null; if (isEmpty && !item.ParameterTypeIsArray) { if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { environment.EmitBadRequest(); environment.EmitStringMessage("Lack of Parameter:" + item.Name); return(null); } } else if (!item.ParameterTypeIsArray) { var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (conv == null) { throw new InvalidOperationException("critical:register code is broken"); } object pValue; if (conv(value ?? values[0], out pValue)) { methodParameters[i] = pValue; continue; } else if (item.IsOptional) { methodParameters[i] = item.DefaultValue; continue; } else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable)) { methodParameters[i] = null; continue; } else { environment.EmitBadRequest(); environment.EmitStringMessage("Mismatch Parameter Type:" + item.Name); return(null); } } var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse); if (arrayConv == null) { throw new InvalidOperationException("critical:register code is broken"); } methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : Enumerable.Empty <string>()); continue; } return(methodParameters); }
// Routing -> ParameterBinding -> Execute public async Task ProcessRequest(IDictionary <string, object> environment) { try { AcceptVerbs verb; string ext; var handler = SelectHandler(environment, out verb, out ext); if (handler == null) { return; } // verb check | TODO:check operation verb attribute if (!options.DefaultAcceptVerb.HasFlag(verb)) { environment.EmitMethodNotAllowed(); return; } // Parameter binding var valueProvider = new ValueProvider(environment, verb); var methodParameters = ParameterBinder.BindParameter(environment, options, valueProvider, handler.Arguments); if (methodParameters == null) { return; } // select formatter var formatter = NegotiateFormat(environment, ext); if (formatter == null) { return; } // Operation execute var context = new OperationContext(environment, handler.ClassName, handler.MethodName, verb) { Parameters = methodParameters, ContentFormatter = formatter, Attributes = handler.AttributeLookup }; await handler.Execute(options, context).ConfigureAwait(false); return; } catch (ReturnStatusCodeException statusException) { statusException.EmitCode(environment); return; } catch (Exception ex) { switch (options.ErrorHandlingPolicy) { case ErrorHandlingPolicy.ReturnInternalServerError: environment.EmitInternalServerError(); return; case ErrorHandlingPolicy.ReturnInternalServerErrorIncludeErrorDetails: environment.EmitInternalServerError(); environment.EmitStringMessage(ex.ToString()); return; case ErrorHandlingPolicy.ThrowException: default: throw; } } }