/// <summary> /// Build QueryValue from query expresion and server response. /// </summary> /// <param name="expression">The query expresion of client request.</param> /// <param name="response">The http response from the server.</param> /// <returns>The baseline QueryValue converted from payload.</returns> public QueryValue BuildQueryValue(QueryExpression expression, HttpResponseData response) { ExceptionUtilities.CheckArgumentNotNull(expression, "expression"); ExceptionUtilities.CheckArgumentNotNull(response, "response"); ExceptionUtilities.CheckAllRequiredDependencies(this); // get type resolver and payload deserializer. var typeResolver = new LinqToAstoriaTypeResolutionVisitor(this.TypeLibrary); // if the response has an error if (response.StatusCode != HttpStatusCode.OK) { return(expression.ExpressionType.CreateErrorValue(new QueryError("Response from server has an error!"))); } string contentType; ExceptionUtilities.Assert(response.Headers.TryGetValue(HttpHeaders.ContentType, out contentType), "Cannot get content type from response."); var deserializer = this.StrategySelector.GetStrategy(contentType, null).GetDeserializer(); this.currentExpression = expression; var expressionForUri = this.ClientSideProjectionReplacer.ReplaceClientSideProjections(expression); ODataUri queryUri = this.QueryToODataUriConverter.ComputeUri(expressionForUri); queryUri.Segments.Insert(0, ODataUriBuilder.Root(this.Workspace.ServiceUri)); // deserialize byte array payload to OData payload element. ODataPayloadElement payload = this.DeserializePayloadData(deserializer, response, queryUri); this.PayloadElementMetadataResolver.ResolveMetadata(payload, queryUri); var normalizer = this.StrategySelector.GetStrategy(contentType, null).GetPayloadNormalizer(); payload = normalizer.Normalize(payload); if (this.ShouldUsePayloadDrivenVerification(queryUri)) { return(this.BuildQueryValueForActionResponse(payload, expression.ExpressionType)); } else { // build query data set from payload for evaluation. It's a different data set from the initial one of current workspace. IQueryDataSet dataSet = this.BuildQueryDataSet(payload); // filter the query and resolve types. Need to remove expressions such as $top, $skip, $orderby, $filter because the returned payload is already the result of performing these expressions. // need to keep root expression, key expression, $expand and $select to have correct anonymous type. var filteredQuery = this.FilterExpression(expression); filteredQuery = typeResolver.ResolveTypes(filteredQuery, this.EvaluationStrategy); // replace the evaluator's query-data-set with the one generated in the payload using (this.Evaluator.WithTemporaryDataSet(dataSet)) { return(this.Evaluator.Evaluate(filteredQuery)); } } }
/// <summary> /// Initializes a new instance of the LinqToAstoriaCustomFunctionResolutionVisitor class /// </summary> /// <param name="typeResolver">The Type Resolution visitor</param> internal LinqToAstoriaCustomFunctionResolutionVisitor(LinqToAstoriaTypeResolutionVisitor typeResolver) { this.typeResolver = typeResolver; }
/// <summary> /// Initializes a new instance of the LinqToAstoriaQueryResolver class. /// </summary> /// <param name="identifierGenerator">Identifier generator.</param> /// <param name="typeLibrary">The query type library.</param> public LinqToAstoriaQueryResolver(IIdentifierGenerator identifierGenerator, QueryTypeLibrary typeLibrary) { this.parameterNameResolutionVisitor = new LinqToAstoriaParameterNameResolutionVisitor(identifierGenerator); this.typeResolver = new LinqToAstoriaTypeResolutionVisitor(typeLibrary); this.customFunctionResolutionVisitor = new LinqToAstoriaCustomFunctionResolutionVisitor(this.typeResolver); }