Exemplo n.º 1
0
		public async Task<MapResult> MapAsync(HttpContextBase context, Type type, MethodInfo method, ParameterInfo parameter)
		{
			context.ThrowIfNull("context");
			type.ThrowIfNull("type");
			method.ThrowIfNull("method");
			parameter.ThrowIfNull("parameter");

			Type parameterType = parameter.ParameterType;
			object model = _container != null ? _container.GetInstance(parameterType) : Activator.CreateInstance(parameterType);
			Type modelType = model.GetType();

			foreach (PropertyInfo property in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
			{
				object mappedValue = await GetMappedValueAsync(context, modelType, property);

				if (mappedValue == null)
				{
					throw new ApplicationException(String.Format("Unable to map property '{0} {1}' of type '{2}'.", property.PropertyType.FullName, property.Name, modelType.FullName));
				}

				property.SetValue(model, mappedValue, null);
			}

			return MapResult.ValueMapped(model);
		}
        public Task<bool> CanMapTypeAsync(HttpContextBase context, Type parameterType)
        {
            context.ThrowIfNull("context");
            parameterType.ThrowIfNull("parameterType");

            return true.AsCompletedTask();
        }
        public Task<ResponseResult> GetResponseAsync(HttpContextBase context, IEnumerable<RouteMatchResult> routeMatchResults)
        {
            context.ThrowIfNull("context");
            routeMatchResults.ThrowIfNull("routeMatchResults");

            return ResponseResult.ResponseGenerated(new Response().NotFound()).AsCompletedTask();
        }
        public override Task<bool> CanMapTypeAsync(HttpContextBase context, Type parameterType)
        {
            context.ThrowIfNull("context");
            parameterType.ThrowIfNull("parameterType");

            return parameterType.ImplementsInterface<IConvertible>().AsCompletedTask();
        }
        public Task<bool> CanMapTypeAsync(HttpContextBase context, Type parameterType)
        {
            context.ThrowIfNull("context");
            parameterType.ThrowIfNull("parameterType");

            return (parameterType == typeof(HttpServerUtilityBase)).AsCompletedTask();
        }
Exemplo n.º 6
0
		public Task<MapResult> MapAsync(HttpContextBase context, Type type, MethodInfo method, ParameterInfo parameter)
		{
			context.ThrowIfNull("request");
			type.ThrowIfNull("type");
			method.ThrowIfNull("method");
			parameter.ThrowIfNull("parameter");

			Type parameterType = parameter.ParameterType;
			var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding);
			string json = reader.ReadToEnd();
			object jsonModel;

			try
			{
				jsonModel = JsonConvert.DeserializeObject(json, parameterType, _serializerSettings);
			}
			catch (Exception exception)
			{
				if (_errorHandling == DataConversionErrorHandling.ThrowException)
				{
					throw new ApplicationException(String.Format("Request content could not be deserialized to '{0}'.", parameterType.FullName), exception);
				}
				jsonModel = parameterType.GetDefaultValue();
			}

			return MapResult.ValueMapped(jsonModel).AsCompletedTask();
		}
Exemplo n.º 7
0
		public async Task<bool> CanMapTypeAsync(HttpContextBase context, Type parameterType)
		{
			context.ThrowIfNull("context");
			parameterType.ThrowIfNull("parameterType");

			return await Task.Run(() => _parameterTypeMatchDelegate(parameterType));
		}
Exemplo n.º 8
0
		public async Task<bool> CanMapTypeAsync(HttpContextBase context, Type parameterType)
		{
			context.ThrowIfNull("context");
			parameterType.ThrowIfNull("parameterType");

			return context.Request.ContentType == "application/json" && await Task.Run(() => _parameterTypeMatchDelegate(parameterType));
		}
        protected override Task<MapResult> OnMapAsync(HttpContextBase context, string value, Type parameterType)
        {
            context.ThrowIfNull("context");
            value.ThrowIfNull("value");
            parameterType.ThrowIfNull("parameterType");

            return MapResult.ValueMapped(((IConvertible)value).ToType(parameterType, CultureInfo.InvariantCulture)).AsCompletedTask();
        }
		public async Task<IEnumerable<object>> GetParameterValuesAsync(HttpContextBase context, Type type, MethodInfo method)
		{
			context.ThrowIfNull("context");
			type.ThrowIfNull("type");
			method.ThrowIfNull("method");

			ParameterInfo[] parameterInfos = method.GetParameters();
			var parameterValues = new List<object>();

			foreach (ParameterInfo parameterInfo in parameterInfos)
			{
				Type parameterType = parameterInfo.ParameterType;
				string parameterName = parameterInfo.Name;
				Type currentParameterType = parameterType;

				do
				{
					bool mapped = false;

					foreach (IParameterMapper parameterMapper in _parameterMappers)
					{
						if (!await parameterMapper.CanMapTypeAsync(context, parameterType))
						{
							continue;
						}
						MapResult mapResult = await parameterMapper.MapAsync(context, type, method, parameterInfo);

						if (mapResult.ResultType == MapResultType.ValueNotMapped)
						{
							continue;
						}

						parameterValues.Add(mapResult.Value);
						mapped = true;
						break;
					}
					if (mapped)
					{
						break;
					}

					currentParameterType = currentParameterType.BaseType;
				} while (currentParameterType != null);

				if (currentParameterType == null)
				{
					throw new ApplicationException(
						String.Format(
							"No request parameter mapper was found for parameter '{0} {1}' of {2}.{3}.",
							parameterType.FullName,
							parameterName,
							type.FullName,
							method.Name));
				}
			}

			return parameterValues;
		}
        public Task<MapResult> MapAsync(HttpContextBase context, Type type, MethodInfo method, ParameterInfo parameter)
        {
            context.ThrowIfNull("context");
            type.ThrowIfNull("type");
            method.ThrowIfNull("method");
            parameter.ThrowIfNull("parameter");

            return MapResult.ValueMapped(context.Server).AsCompletedTask();
        }
		public async Task<ResponseHandlerResult> HandleResponseAsync(HttpContextBase context, IResponse suggestedResponse, ICache cache, string cacheKey)
		{
			context.ThrowIfNull("context");
			suggestedResponse.ThrowIfNull("suggestedResponse");

			await new CacheResponse(suggestedResponse).WriteResponseAsync(context.Response);

			return ResponseHandlerResult.ResponseWritten();
		}
        public Task<ResponseResult> GetResponseAsync(HttpContextBase context, IEnumerable<RouteMatchResult> routeMatchResults)
        {
            context.ThrowIfNull("context");
            routeMatchResults.ThrowIfNull("routeMatchResults");

            RouteMatchResult[] unmatchedResults = routeMatchResults.Where(arg => arg.MatchResult.ResultType == MatchResultType.RouteNotMatched).ToArray();

            if (!unmatchedResults.Any())
            {
                return ResponseResult.ResponseNotGenerated().AsCompletedTask();
            }

            RouteMatchResult[] unmatchedResultsThatMatchedOnUrlRelativePath = unmatchedResults.Where(arg1 => RouteMatchedUrlRelativePath(arg1.MatchResult)).ToArray();
            int minimumUnmatchedRestrictions = unmatchedResultsThatMatchedOnUrlRelativePath.Any() ? unmatchedResultsThatMatchedOnUrlRelativePath.Min(arg => arg.MatchResult.UnmatchedRestrictions.Count()) : 0;
            RouteMatchResult[] closestMatches = unmatchedResultsThatMatchedOnUrlRelativePath.Where(arg => arg.MatchResult.UnmatchedRestrictions.Count() == minimumUnmatchedRestrictions).ToArray();

            if (closestMatches.Length != 1)
            {
                return ResponseResult.ResponseNotGenerated().AsCompletedTask();
            }

            RouteMatchResult closestMatch = closestMatches[0];
            IRestriction[] unmatchedRestrictions = closestMatch.MatchResult.UnmatchedRestrictions.ToArray();
            MethodRestriction[] methodRestrictions = unmatchedRestrictions.OfType<MethodRestriction>().ToArray();

            if (methodRestrictions.Any())
            {
                IEnumerable<string> methods = methodRestrictions
                    .Select(arg => arg.Method)
                    .Distinct(StringComparer.OrdinalIgnoreCase)
                    .OrderBy(arg => arg);

                return ResponseResult.ResponseGenerated(new Response().MethodNotAllowed().Header("Allow", String.Join(", ", methods))).AsCompletedTask();
            }
            if (unmatchedRestrictions.OfType<HeaderRestriction<AcceptHeader>>().Any())
            {
                return ResponseResult.ResponseGenerated(new Response().NotAcceptable()).AsCompletedTask();
            }
            if (unmatchedRestrictions.OfType<HeaderRestriction<AcceptCharsetHeader>>().Any())
            {
                return ResponseResult.ResponseGenerated(new Response().NotAcceptable()).AsCompletedTask();
            }
            if (unmatchedRestrictions.OfType<HeaderRestriction<AcceptEncodingHeader>>().Any())
            {
                return ResponseResult.ResponseGenerated(new Response().NotAcceptable()).AsCompletedTask();
            }
            if (unmatchedRestrictions.OfType<HeaderRestriction<ContentEncodingHeader>>().Any())
            {
                return ResponseResult.ResponseGenerated(new Response().UnsupportedMediaType()).AsCompletedTask();
            }

            return ResponseResult.ResponseNotGenerated().AsCompletedTask();
        }
Exemplo n.º 14
0
        public Task<MapResult> MapAsync(HttpContextBase context, Type modelType, PropertyInfo property)
        {
            context.ThrowIfNull("context");
            modelType.ThrowIfNull("modelType");
            property.ThrowIfNull("property");

            Type propertyType = property.PropertyType;
            string propertyName = property.Name;
            NameValueCollection nameValueCollection;

            switch (_source)
            {
                case NameValueCollectionSource.Form:
                    nameValueCollection = context.Request.Form;
                    break;
                case NameValueCollectionSource.QueryString:
                    nameValueCollection = context.Request.QueryString;
                    break;
                default:
                    throw new InvalidOperationException(String.Format("Unexpected name-value collection source {0}.", _source));
            }
            string field = nameValueCollection.AllKeys.LastOrDefault(arg => String.Equals(arg, propertyName, _caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase));

            if (field == null)
            {
                return MapResult.ValueNotMapped().AsCompletedTask();
            }

            string value = nameValueCollection[field];

            try
            {
                return OnMapAsync(context, value, propertyType);
            }
            catch (Exception exception)
            {
                if (_errorHandling == DataConversionErrorHandling.ThrowException)
                {
                    throw new ApplicationException(
                        String.Format(
                            "Value of form field '{0}' could not be converted to property '{1} {2}' of type '{3}'.",
                            field,
                            propertyType.FullName,
                            propertyName,
                            modelType.FullName),
                        exception);
                }

                return MapResult.ValueMapped(propertyType.GetDefaultValue()).AsCompletedTask();
            }
        }
Exemplo n.º 15
0
		public Task<MapResult> MapAsync(HttpContextBase context, Type type, MethodInfo method, ParameterInfo parameter)
		{
			context.ThrowIfNull("context");
			type.ThrowIfNull("type");
			method.ThrowIfNull("method");
			parameter.ThrowIfNull("parameter");

			Type parameterType = parameter.ParameterType;
			string parameterName = parameter.Name;
			string field = context.Request.Form.AllKeys.LastOrDefault(arg => String.Equals(arg, parameterName, _caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase));

			if (field == null)
			{
				return MapResult.ValueNotMapped().AsCompletedTask();
			}

			IConvertible value = context.Request.Form[field];
			object convertedValue;

			try
			{
				convertedValue = value.ToType(parameterType, CultureInfo.InvariantCulture);
			}
			catch (Exception exception)
			{
				if (_errorHandling == DataConversionErrorHandling.ThrowException)
				{
					throw new ApplicationException(
						String.Format(
							"Value for form field '{0}' could not be converted to parameter '{1} {2}' of {3}.{4}.",
							field,
							parameterType.FullName,
							parameterName,
							type.FullName,
							method.Name),
						exception);
				}
				convertedValue = parameterType.GetDefaultValue();
			}

			return MapResult.ValueMapped(convertedValue).AsCompletedTask();
		}
		public async Task<ResponseResult> GetResponseAsync(HttpContextBase context, IEnumerable<RouteMatchResult> routeMatchResults)
		{
			context.ThrowIfNull("context");
			routeMatchResults.ThrowIfNull("routeMatchResults");

			routeMatchResults = routeMatchResults.ToArray();

			RouteMatchResult[] matchedResults = routeMatchResults.Where(arg => arg.MatchResult.ResultType == MatchResultType.RouteMatched).ToArray();

			if (!matchedResults.Any())
			{
				return ResponseResult.ResponseNotGenerated();
			}

			int maximumMatchedRestrictions = matchedResults.Max(arg => arg.MatchResult.MatchedRestrictions.Count());
			RouteMatchResult[] bestMatches = matchedResults.Where(arg => arg.MatchResult.MatchedRestrictions.CountEqual(maximumMatchedRestrictions)).ToArray();

			if (bestMatches.Length > 1)
			{
				return ResponseResult.ResponseGenerated(new Response().MultipleChoices());
			}
			if (bestMatches.Length == 0)
			{
				return ResponseResult.ResponseNotGenerated();
			}

			RouteMatchResult bestMatch = bestMatches[0];
			AuthenticateResult authenticateResult = await bestMatch.Route.AuthenticateAsync(context.Request, context.Response);

			if (authenticateResult.ResultType == AuthenticateResultType.AuthenticationFailed)
			{
				return ResponseResult.ResponseGenerated(authenticateResult.FailedResponse ?? new Response().Unauthorized());
			}

			Task<IResponse> responseTask = bestMatch.Route.ProcessResponseAsync(context);

			return ResponseResult.ResponseGenerated(responseTask, bestMatch.MatchResult.CacheKey);
		}
		public async Task<ResponseHandlerResult> HandleResponseAsync(HttpContextBase context, IResponse suggestedResponse, ICache cache, string cacheKey)
		{
			context.ThrowIfNull("context");
			suggestedResponse.ThrowIfNull("suggestedResponse");

			StatusAndSubStatusCode statusCode = suggestedResponse.StatusCode;

			if (!_statusCodes.Contains(statusCode))
			{
				return ResponseHandlerResult.ResponseNotHandled();
			}

			AcceptHeader[] acceptHeaders = AcceptHeader.ParseMany(context.Request.Headers["Accept"]).ToArray();

			if (acceptHeaders.Any() && !acceptHeaders.Any(arg => arg.MediaTypeMatches("text/plain")))
			{
				return ResponseHandlerResult.ResponseNotHandled();
			}

			string content = String.Format(
				"HTTP {0}{1} {2}",
				statusCode.StatusCode,
				statusCode.SubStatusCode == 0 ? "" : "." + statusCode.SubStatusCode.ToString(CultureInfo.InvariantCulture),
				statusCode.StatusDescription.Length > 0 ? String.Format("({0})", statusCode.StatusDescription) : "");
			Response response = new Response(statusCode)
				.TextPlain()
				.Content(content);

			response.CachePolicy.NoClientCaching();

			await new CacheResponse(response).WriteResponseAsync(context.Response);

			context.Response.TrySkipIisCustomErrors = true;

			return ResponseHandlerResult.ResponseWritten();
		}
Exemplo n.º 18
0
		public async Task<ResponseHandlerResult> HandleResponseAsync(HttpContextBase context, IResponse suggestedResponse, ICache cache, string cacheKey)
		{
			context.ThrowIfNull("context");
			suggestedResponse.ThrowIfNull("suggestedResponse");

			if (!suggestedResponse.CachePolicy.HasPolicy || cache == null || cacheKey == null)
			{
				return ResponseHandlerResult.ResponseNotHandled();
			}

			CacheItem cacheItem = await cache.GetAsync(cacheKey);
			string responseETag = suggestedResponse.CachePolicy.ETag;

			#region If-Match precondition header

			IfMatchHeader[] ifMatchHeaders = IfMatchHeader.ParseMany(context.Request.Headers["If-Match"]).ToArray();

			// Only consider If-Match headers if response status code is 2xx or 412
			if (ifMatchHeaders.Any() && ((suggestedResponse.StatusCode.StatusCode >= 200 && suggestedResponse.StatusCode.StatusCode <= 299) || suggestedResponse.StatusCode.StatusCode == 412))
			{
				// Return 412 if no If-Match header matches the response ETag
				// Return 412 if an "If-Match: *" header is present and the response has no ETag
				if (ifMatchHeaders.All(arg => arg.EntityTag.Value != responseETag) ||
				    (responseETag == null && ifMatchHeaders.Any(arg => arg.EntityTag.Value == "*")))
				{
					return await WriteResponseAsync(context.Response, new Response().PreconditionFailed());
				}
			}

			#endregion

			#region If-None-Match precondition header

			IfNoneMatchHeader[] ifNoneMatchHeaders = IfNoneMatchHeader.ParseMany(context.Request.Headers["If-None-Match"]).ToArray();

			if (ifNoneMatchHeaders.Any())
			{
				// Return 304 if an If-None-Match header matches the response ETag and the request method was GET or HEAD
				// Return 304 if an "If-None-Match: *" header is present, the response has an ETag and the request method was GET or HEAD
				// Return 412 if an "If-None-Match: *" header is present, the response has an ETag and the request method was not GET or HEAD
				if (ifNoneMatchHeaders.Any(arg => arg.EntityTag.Value == responseETag) ||
				    (ifNoneMatchHeaders.Any(arg => arg.EntityTag.Value == "*") && responseETag != null))
				{
					if (String.Equals(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) || String.Equals(context.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase))
					{
						if (cacheItem != null)
						{
							cacheItem.Response.CachePolicy.Apply(context.Response.Cache);
						}
						else
						{
							suggestedResponse.CachePolicy.Apply(context.Response.Cache);
						}

						return await WriteResponseAsync(context.Response, new Response().NotModified());
					}

					return await WriteResponseAsync(context.Response, new Response().PreconditionFailed());
				}
			}

			#endregion

			#region If-Modified-Since precondition header

			IfModifiedSinceHeader ifModifiedSinceHeader = IfModifiedSinceHeader.Parse(context.Request.Headers["If-Modified-Since"]);
			bool validIfModifiedSinceHttpDate = ifModifiedSinceHeader != null && ifModifiedSinceHeader.HttpDate <= _systemClock.UtcDateTime;

			// Only consider an If-Modified-Since header if response status code is 200 and the HTTP-date is valid
			if (suggestedResponse.StatusCode.ParsedStatusCode == HttpStatusCode.OK && validIfModifiedSinceHttpDate)
			{
				// Return 304 if the response was cached before the HTTP-date
				if (cacheItem != null && cacheItem.CachedUtcTimestamp < ifModifiedSinceHeader.HttpDate)
				{
					return await WriteResponseAsync(context.Response, new Response().NotModified());
				}
			}

			#endregion

			#region If-Unmodified-Since precondition header

			IfUnmodifiedSinceHeader ifUnmodifiedSinceHeader = IfUnmodifiedSinceHeader.Parse(context.Request.Headers["If-Unmodified-Since"]);
			bool validIfUnmodifiedSinceHttpDate = ifUnmodifiedSinceHeader != null && ifUnmodifiedSinceHeader.HttpDate <= _systemClock.UtcDateTime;

			// Only consider an If-Unmodified-Since header if response status code is 2xx or 412 and the HTTP-date is valid
			if (((suggestedResponse.StatusCode.StatusCode >= 200 && suggestedResponse.StatusCode.StatusCode <= 299) || suggestedResponse.StatusCode.StatusCode == 412) && validIfUnmodifiedSinceHttpDate)
			{
				// Return 412 if the previous response was removed from the cache or was cached again at a later time
				if (cacheItem == null || cacheItem.CachedUtcTimestamp >= ifUnmodifiedSinceHeader.HttpDate)
				{
					return await WriteResponseAsync(context.Response, new Response().PreconditionFailed());
				}
			}

			#endregion

			#region No server caching

			// Do not cache the response when the response sends a non-cacheable status code, or when an Authorization header is present
			if (!_cacheableStatusCodes.Contains(suggestedResponse.StatusCode) || context.Request.Headers["Authorization"] != null)
			{
				return await WriteResponseAsync(context.Response, suggestedResponse);
			}

			CacheControlHeader cacheControlHeader = CacheControlHeader.Parse(context.Request.Headers["Cache-Control"]);

			// Do not cache the response if a "Cache-Control: no-cache" or "Cache-Control: no-store" header is present
			if (cacheControlHeader != null && (cacheControlHeader.NoCache || cacheControlHeader.NoStore))
			{
				return await WriteResponseAsync(context.Response, suggestedResponse);
			}

			IEnumerable<PragmaHeader> pragmaHeader = PragmaHeader.ParseMany(context.Request.Headers["Pragma"]);

			// Do not cache the response if a "Pragma: no-cache" header is present
			if (pragmaHeader.Any(arg => String.Equals(arg.Name, "no-cache", StringComparison.OrdinalIgnoreCase)))
			{
				return await WriteResponseAsync(context.Response, suggestedResponse);
			}

			#endregion

			// Return 504 if the response has not been cached but the client is requesting to receive only a cached response
			if (cacheItem == null && cacheControlHeader != null && cacheControlHeader.OnlyIfCached)
			{
				return await WriteResponseAsync(context.Response, new Response().GatewayTimeout());
			}

			if (cacheItem != null)
			{
				// Write the cached response if no Cache-Control header is present
				// Write the cached response if a "Cache-Control: max-age" header is validated
				// Write the cached response if a "Cache-Control: max-stale" header is validated
				// Write the cached response if a "Cache-Control: min-fresh" header is validated
				if (cacheControlHeader == null ||
				    _systemClock.UtcDateTime - cacheItem.CachedUtcTimestamp <= cacheControlHeader.MaxAge ||
				    cacheControlHeader.OnlyIfCached ||
				    cacheItem.ExpiresUtcTimestamp == null ||
				    _systemClock.UtcDateTime - cacheItem.ExpiresUtcTimestamp.Value <= cacheControlHeader.MaxStale ||
				    cacheItem.ExpiresUtcTimestamp.Value - _systemClock.UtcDateTime < cacheControlHeader.MinFresh)
				{
					return await WriteResponseInCacheAsync(context.Response, cacheItem);
				}
			}

			bool cacheOnServer = suggestedResponse.CachePolicy.AllowsServerCaching;
			var cacheResponse = new CacheResponse(suggestedResponse);

			if (cacheOnServer)
			{
				DateTime expirationUtcTimestamp = suggestedResponse.CachePolicy.ServerCacheExpirationUtcTimestamp != null
					                                  ? suggestedResponse.CachePolicy.ServerCacheExpirationUtcTimestamp.Value
					                                  : _systemClock.UtcDateTime + suggestedResponse.CachePolicy.ServerCacheMaxAge.Value;

				await cache.AddAsync(cacheKey, cacheResponse, expirationUtcTimestamp);
			}

			return await WriteResponseAsync(context.Response, cacheResponse);
		}