public static TResult ParseContentDelegate <TResult>(string key, IFormCollection formData, ParameterInfo parameterInfo, IApplication httpApp, Func <object, TResult> onParsed, Func <string, TResult> onFailure) { return(ParseContentDelegate(key, formData, (strValue) => { return httpApp.Bind(strValue, parameterInfo, (value) => { return onParsed(value); }, why => onFailure(why)); }, formFile => { return httpApp.Bind(formFile, parameterInfo, (value) => { return onParsed(value); }, why => onFailure(why)); }, onFailure: onFailure)); }
protected override CastDelegate GetFileNameCastDelegate( IHttpRequest request, IApplication httpApp, string[] componentsMatched, out string[] pathKeys) { pathKeys = PathComponents(request) .Skip(componentsMatched.Length + 1) .ToArray(); var paths = pathKeys; CastDelegate fileNameCastDelegate = (paramInfo, onParsed, onFailure) => { if (!paths.Any()) { return(onFailure("No URI filename value provided.")); } if (paths.Length > 1) { return(onFailure($"More than 1 path key `{paths.Join(',')}` not supported.")); } return(httpApp.Bind(paths.First(), paramInfo, v => onParsed(v), (why) => onFailure(why))); }; return(fileNameCastDelegate); }
public static TResult Bind <TProvider, TResult>(this IApplication application, TProvider provider, MemberInfo propertyOrFieldInfo, Func <object, TResult> onParsed, Func <string, TResult> onFailureToBind) { return(propertyOrFieldInfo .GetAttributesInterface <IBindApiPropertyOrField <TProvider> >() .First( (propBinder, next) => { return propBinder.Bind <TResult>(propertyOrFieldInfo, provider, application, onParsed, (why) => { return next(); }, (why) => onFailureToBind(why)); }, () => { var type = propertyOrFieldInfo.GetPropertyOrFieldType(); return application.Bind(provider, type, onParsed, onFailureToBind); })); }
public async Task <T> BindFromByte <T>() { var bytes = await content.OpenReadStream().ToBytesAsync(); var result = application.Bind(bytes, typeof(T), (v) => (T)v, why => throw new Exception(why)); return(result); }
public TResult ParseContentDelegate <TResult>(JContainer contentJContainer, string contentString, Serialization.BindConvert bindConvert, ParameterInfo paramInfo, IApplication httpApp, IHttpRequest request, Func <object, TResult> onParsed, Func <string, TResult> onFailure) { if (contentJContainer is JObject) { var contentJObject = contentJContainer as JObject; var key = this.GetKey(paramInfo); return(ParseJsonContentDelegate(contentJObject, contentString, bindConvert, key, paramInfo, httpApp, request, onParsed, onFailure)); } if (contentJContainer is JArray) { var contentJArray = contentJContainer as JArray; var paramType = paramInfo.ParameterType; var key = this.GetKey(paramInfo); if (paramType.IsArray) { var elementType = paramType.GetElementType(); var arrayOfType = contentJArray .Select( contentJToken => { if (contentJToken is JObject) { var contentJObject = (JObject)contentJToken; if (!contentJObject.TryGetValue(key, out JToken valueToken)) { return(elementType.GetDefault()); } return(httpApp.Bind(valueToken, elementType, obj => obj, why => elementType.GetDefault())); } return(elementType.GetDefault()); }) .CastArray(elementType); return(onParsed(arrayOfType)); } } return(onFailure($"JSON Content is {contentJContainer.Type} and non-array properties can only be parsed from objects.")); }
internal static TResult ContentToType <TResult>(IApplication httpApp, ParameterInfo paramInfo, MultipartContentTokenParser tokenReader, Func <object, TResult> onParsed, Func <string, TResult> onFailure) { var type = paramInfo.ParameterType; return(ContentToType(httpApp, type, tokenReader, onParsed, strValue => { return httpApp.Bind(strValue, paramInfo, (value) => { return onParsed(value); }, why => onFailure(why)); })); }
public static TResult ParseJsonContentDelegate <TResult>(JObject contentJObject, string contentString, Serialization.BindConvert bindConvert, string key, ParameterInfo paramInfo, IApplication httpApp, IHttpRequest request, Func <object, TResult> onParsed, Func <string, TResult> onFailure) { if (!contentJObject.TryGetValue(key, out JToken valueToken)) { return(onFailure($"Key[{key}] was not found in JSON")); } try { //var tokenParser = new Serialization.JsonTokenParser(valueToken); return(httpApp.Bind(valueToken, paramInfo, obj => onParsed(obj), (why) => { // TODO: Get BindConvert to StandardJTokenBindingAttribute if (valueToken.Type == JTokenType.Object || valueToken.Type == JTokenType.Array) { try { var value = Newtonsoft.Json.JsonConvert.DeserializeObject( valueToken.ToString(), paramInfo.ParameterType, bindConvert); return onParsed(value); } catch (Newtonsoft.Json.JsonSerializationException) { throw; } } return onFailure(why); })); } catch (Exception ex) { return(onFailure(ex.Message)); } }
public TResult ParseContentDelegate <TResult>(XmlDocument xmlDoc, string rawContent, ParameterInfo parameterInfo, IApplication httpApp, IHttpRequest request, Func <object, TResult> onParsed, Func <string, TResult> onFailure) { if (parameterInfo.ParameterType.IsAssignableFrom(typeof(XmlDocument))) { return(onParsed(xmlDoc)); } var mgr = new XmlNamespaceManager(xmlDoc.NameTable); if (NSPrefix.HasBlackSpace()) { mgr.AddNamespace(NSPrefix, NSUri); } var key = this.GetKey(parameterInfo); var node = xmlDoc.SelectSingleNode(key, mgr); if (parameterInfo.ParameterType.IsAssignableFrom(typeof(XmlNode))) { return(onParsed(node)); } if (parameterInfo.ParameterType.IsAssignableFrom(typeof(XmlNode[]))) { if (node.IsDefaultOrNull()) { return(onParsed(new XmlNode[] { })); } return(onParsed( XmlContent .Enumerate(node.ChildNodes) .AsArray())); } return(httpApp.Bind(node, parameterInfo, onParsed, onFailure)); }
protected virtual CastDelegate GetFileNameCastDelegate( IHttpRequest request, IApplication httpApp, string [] componentsMatched, out string [] pathKeys) { pathKeys = PathComponents(request) .Skip(componentsMatched.Length) .ToArray(); var path = pathKeys; CastDelegate fileNameCastDelegate = (paramInfo, onParsed, onFailure) => { if (!path.Any()) { return(onFailure("No URI filename value provided.")); } var fileName = path.First(); return(httpApp.Bind(fileName, paramInfo, v => onParsed(v), (why) => onFailure(why))); }; return(fileNameCastDelegate); }
protected virtual CastDelegate GetQueryCastDelegate( IHttpRequest request, IApplication httpApp, out string[] queryKeys) { var queryParameters = request.RequestUri.ParseQuery() .Select(kvp => kvp.Key.ToLower().PairWithValue(kvp.Value)) .ToDictionary(); queryKeys = queryParameters.SelectKeys().ToArray(); var queryParameterCollections = GetCollectionParameters(httpApp, queryParameters).ToDictionary(); CastDelegate queryCastDelegate = (paramInfo, onParsed, onFailure) => { var queryKey = paramInfo .GetAttributeInterface <IBindApiValue>() .GetKey(paramInfo) .ToLower(); var type = paramInfo.ParameterType; if (!queryParameters.ContainsKey(queryKey)) { if (!queryParameterCollections.ContainsKey(queryKey)) { return(onFailure($"Missing query parameter `{queryKey}`")); } return(queryParameterCollections[queryKey]( type, vs => onParsed(vs), why => onFailure(why))); } var queryValueString = queryParameters[queryKey]; return(httpApp.Bind(queryValueString, paramInfo, v => onParsed(v), (why) => onFailure(why))); }; return(queryCastDelegate); }
public static IEnumerable <KeyValuePair <string, ParseContentDelegate <SelectParameterResult> > > GetCollectionParameters(IApplication httpApp, IEnumerable <KeyValuePair <string, string> > queryParameters) { // Convert parameters into Collections if necessary return(queryParameters .SelectOptional <KeyValuePair <string, string>, MultipartParameter>( (param, select, skip) => param.Key.MatchRegexInvoke( @"(?<key>[a-zA-Z0-9]+)\[(?<value>[a-zA-Z0-9]+)\]", (string key, string value) => new KeyValuePair <string, string>(key, value), (kvps) => { if (!kvps.Any()) { return skip(); } var kvp = kvps.First(); var multipartParam = new MultipartParameter { index = kvp.Key, key = kvp.Value, fetchValue = (type, onSuccess, onFailure) => httpApp.Bind(param.Value, type, v => onSuccess(v), why => onFailure(why)) .AsTask(), }; return select(multipartParam); })) .GroupBy(collectionParameter => collectionParameter.index) .Select( collectionParameterGrp => collectionParameterGrp.Key.ToLower() .PairWithValue <string, ParseContentDelegate <SelectParameterResult> >( (collectionType, onParsed, onFailure) => { if (collectionType.IsGenericType) { var genericArgs = collectionType.GenericTypeArguments; if (genericArgs.Length == 1) { // It's an array var typeToCast = genericArgs.First(); var lookup = collectionParameterGrp .SelectOptional <MultipartParameter, object>( (collectionParameter, next, skip) => (EastFive.Linq.EnumerableExtensions.ISelected <object>)collectionParameter.fetchValue(typeToCast, v => next(v), (why) => skip())) .ToArray(); return onParsed(lookup); } if (genericArgs.Length == 2) { // It's an dictionary var typeToCast = genericArgs[1]; var kvpCreateMethod = typeof(FunctionViewControllerAttribute).GetMethod("KvpCreate", BindingFlags.Static | BindingFlags.NonPublic); var correctGenericKvpCreate = kvpCreateMethod.MakeGenericMethod(genericArgs); var lookup = collectionParameterGrp .FlatMap( (collectionParameter, next, skip) => (object[])collectionParameter.fetchValue(typeToCast, v => next(correctGenericKvpCreate.Invoke(null, new object[] { collectionParameter.key, v })), (why) => skip()), (IEnumerable <object> lookupInner) => lookupInner.ToArray()); var castMethod = typeof(FunctionViewControllerAttribute).GetMethod("CastToKvp", BindingFlags.Static | BindingFlags.NonPublic); var correctKvpsCast = castMethod.MakeGenericMethod(genericArgs); var kvpsOfCorrectTypes = correctKvpsCast.Invoke(null, lookup.AsArray()); var dictCreateMethod = typeof(FunctionViewControllerAttribute).GetMethod("DictionaryCreate", BindingFlags.Static | BindingFlags.NonPublic); var correctGenericDictCreate = dictCreateMethod.MakeGenericMethod(genericArgs); var dictionaryOfCorrectTypes = correctGenericDictCreate.Invoke(null, kvpsOfCorrectTypes.AsArray()); return onParsed(dictionaryOfCorrectTypes); } return onFailure($"Cannot parse collection of type {collectionType.FullName}"); } if (typeof(Enumerable).IsAssignableFrom(collectionType)) { // It's an array var typeToCast = typeof(object); var values = collectionParameterGrp .Select( (collectionParameter) => (SelectedValue?)collectionParameter.fetchValue(typeToCast, v => new SelectedValue { value = v }, (why) => default(SelectedValue?))) .SelectWhereHasValue() .Select(v => v.value); return onParsed(values); } if (typeof(System.Collections.DictionaryBase).IsAssignableFrom(collectionType)) { // It's an dictionary var typeToCast = typeof(object); var dictionary = collectionParameterGrp .FlatMap( (collectionParameter, next, skip) => (Dictionary <string, object>)collectionParameter.fetchValue(typeToCast, v => next(collectionParameter.key.PairWithValue(v)), (why) => skip()), (IEnumerable <KeyValuePair <string, object> > lookups) => lookups.ToDictionary()); return onParsed(dictionary); } return onFailure($"Cannot parse collection of type {collectionType.FullName}"); }))); }
public TResult Bind <TResult>(Type type, IFormFile content, IApplication application, Func <object, TResult> onParsed, Func <string, TResult> onDidNotBind, Func <string, TResult> onBindingFailure) { if (type.IsAssignableFrom(typeof(Stream))) { var streamValue = content.OpenReadStream(); return(onParsed((object)streamValue)); } if (type.IsAssignableFrom(typeof(Func <Task <Stream> >))) { Func <Task <Stream> > callbackValue = () => { var streamValue = content.OpenReadStream(); return(streamValue.AsTask()); }; return(onParsed((object)callbackValue)); } if (type.IsAssignableFrom(typeof(byte[]))) { var stream = content.OpenReadStream(); var bytes = new byte[content.Length]; stream.Read(bytes, 0, (int)content.Length); return(onParsed((object)bytes)); } if (type.IsAssignableFrom(typeof(Func <Task <byte[]> >))) { Func <Task <byte[]> > callbackValue = () => { var stream = content.OpenReadStream(); var bytes = new byte[content.Length]; stream.Read(bytes, 0, (int)content.Length); return(bytes.AsTask()); }; return(onParsed((object)callbackValue)); } if (type.IsAssignableFrom(typeof(MediaTypeWithQualityHeaderValue))) { var header = new MediaTypeWithQualityHeaderValue(content.ContentType); return(onParsed(header)); } if (type.IsAssignableFrom(typeof(ContentDispositionHeaderValue))) { if (ContentDispositionHeaderValue.TryParse(content.ContentDisposition, out ContentDispositionHeaderValue header)) { return(onParsed((object)header)); } } if (type.IsSubClassOfGeneric(typeof(ReadRequestBodyDelegateAsync <>))) { var data = new Data(content, application); var requestDelegate = InvokeHelper(data.BindFromByte <object>, type, data); return(onParsed(requestDelegate)); } var bytesGeneric = content.OpenReadStream().ToBytesAsync().Result; return(application.Bind(bytesGeneric, type, (v) => onParsed(v), why => onDidNotBind(why))); //return onDidNotBind( // $"{type.FullName} is not supported from Form Data. Consider wrapping it as a ReadRequestBodyDelegateAsync<>"); }
public static TResult Bind <TProvider, TResult>(this IApplication application, TProvider provider, ParameterInfo parameter, Func <object, TResult> onParsed, Func <string, TResult> onFailureToBind) { return(parameter .GetAttributesInterface <IBindApiParameter <TProvider> >() .First( (paramBinder, next) => { return paramBinder.Bind(parameter, provider, application, onParsed, (why) => { return next(); }, (why) => onFailureToBind(why)); }, () => { return application.GetType() .GetAttributesInterface <IBindApiParameter <TProvider> >(true) .First( (paramBinder, next) => { return paramBinder.Bind(parameter, provider, application, onParsed, (why) => { return next(); }, (why) => onFailureToBind(why)); }, () => { var parameterType = parameter.ParameterType; return parameterType .GetAttributesInterface <IBindApiParameter <TProvider> >(inherit: true) .First( (paramBinder, next) => { return paramBinder.Bind(parameter, provider, application, onParsed, (why) => { return next(); }, (why) => onFailureToBind(why)); }, () => { return application.Bind(provider, parameterType, onParsed, onFailureToBind); }); }); })); }