/// <summary> /// Creates the result object for the specified query parameters. /// </summary> /// <param name="source">The source object for the request.</param> /// <param name="context">The data service context.</param> /// <param name="callback">The AsyncCallback delegate.</param> /// <param name="state">The state object for the callback.</param> /// <param name="method">async method name at the source.</param> /// <returns>Result representing the create request. The request has not been initiated yet.</returns> private QueryResult CreateExecuteResult(object source, DataServiceContext context, AsyncCallback callback, object state, string method) { Debug.Assert(null != context, "context is null"); QueryComponents qc = this.QueryComponents(context.Model); RequestInfo requestInfo = new RequestInfo(context); Debug.Assert( string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0 || string.CompareOrdinal(XmlConstants.HttpMethodGet, qc.HttpMethod) == 0, "Only get and post are supported in the execute pipeline, which should have been caught earlier"); if (qc.UriOperationParameters != null) { Debug.Assert(qc.UriOperationParameters.Any(), "qc.UriOperationParameters.Any()"); Serializer serializer = new Serializer(requestInfo); this.RequestUri = serializer.WriteUriOperationParametersToUri(this.RequestUri, qc.UriOperationParameters); } HeaderCollection headers = new HeaderCollection(); if (string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0) { if (qc.BodyOperationParameters == null) { // set the content length to be 0 if there are no operation parameters. headers.SetHeader(XmlConstants.HttpContentLength, "0"); } else { context.Format.SetRequestContentTypeForOperationParameters(headers); } } // Validate and set the request DSV and MDSV header headers.SetRequestVersion(qc.Version, requestInfo.MaxProtocolVersionAsVersion); requestInfo.Format.SetRequestAcceptHeaderForQuery(headers, qc); // We currently do not have a descriptor to expose to the user for invoking something through Execute. Ideally we could expose an OperationDescriptor. ODataRequestMessageWrapper requestMessage = new RequestInfo(context).WriteHelper.CreateRequestMessage(context.CreateRequestArgsAndFireBuildingRequest(qc.HttpMethod, this.RequestUri, headers, context.HttpStack, null /*descriptor*/)); requestMessage.FireSendingRequest2(null /*descriptor*/); QueryResult queryResult = null; if (qc.BodyOperationParameters != null) { Debug.Assert( string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0, "qc.HttpMethod == XmlConstants.HttpMethodPost"); Debug.Assert(qc.BodyOperationParameters.Any(), "unexpected body operation parameter count of zero."); Serializer serializer = new Serializer(requestInfo); serializer.WriteBodyOperationParameters(qc.BodyOperationParameters, requestMessage); // pass in the request stream so that request payload can be written to the http webrequest. queryResult = new QueryResult(source, method, this, requestMessage, requestInfo, callback, state, requestMessage.CachedRequestStream); } else { queryResult = new QueryResult(source, method, this, requestMessage, requestInfo, callback, state); } return(queryResult); }
/// <summary> /// Fire SendingRequest event if its conditions are met. /// If the user has a handler for BuildingRequest, we will throw. /// If the user has no BuildingRequest handlers but does have a SendingRequest2 handler, we silently do not fire this event (this is shipped 5.0 behavior). /// </summary> private void FireSendingRequest() { // Do not fire SendingRequest event when user tries to wrap the HttpWebRequestMessage if (this.fireSendingRequestMethodCalled || this.requestInfo == null) { return; } // We need to set this before SendingRequest event is fired so that // GetStream method can throw if it is called from SendingRequest event. this.fireSendingRequestMethodCalled = true; HeaderCollection cachedHeaders = null; if (this.requestInfo.HasSendingRequestEventHandlers) { // Before firing SendingRequest event, we need to cache all the header values so that // we can reset them to the original values after SendingRequest event has been fired. cachedHeaders = new HeaderCollection(); foreach (var header in this.Headers) { cachedHeaders.SetHeader(header.Key, header.Value); } #if PORTABLELIB cachedHeaders.SetHeader(XmlConstants.HttpContentLength, this.httpRequest.Headers[XmlConstants.HttpContentLength]); #endif #if !ASTORIA_LIGHT && !PORTABLELIB // Content-Length and accept header does not show up in the header collection at all. // Hence adding it explicitly, since we reset the content length header // after firing SendingRequest event cachedHeaders.SetHeader(XmlConstants.HttpContentLength, this.httpRequest.ContentLength.ToString(CultureInfo.InvariantCulture)); #endif } // Fires whenever a new HttpWebRequest has been created // The event fires early - before the client library sets many of its required property values. // This ensures the client library has the last say on the value of mandated properties // such as the HTTP verb being used for the request. if (this.requestInfo.HasSendingRequestEventHandlers) { System.Net.WebHeaderCollection requestHeaders; #if !ASTORIA_LIGHT requestHeaders = this.httpRequest.Headers; SendingRequestEventArgs args = new SendingRequestEventArgs(this.httpRequest, requestHeaders); #else requestHeaders = this.httpRequest.CreateEmptyWebHeaderCollection(); /* Also set header for SL, MaxDataServcieVersion is required header */ foreach (var head in this.Headers) { if (head.Key == XmlConstants.HttpMaxDataServiceVersion) { requestHeaders[XmlConstants.HttpMaxDataServiceVersion] = head.Value; break; } } SendingRequestEventArgs args = new SendingRequestEventArgs(null, requestHeaders); #endif this.requestInfo.FireSendingRequest(args); #if !ASTORIA_LIGHT if (!Object.ReferenceEquals(args.Request, this.httpRequest)) { this.httpRequest = (System.Net.HttpWebRequest)args.Request; } #else // apply all headers to the request foreach (string key in requestHeaders.AllKeys) { this.httpRequest.Headers[key] = requestHeaders[key]; } #endif HttpWebRequestMessage.SetHeaderValues(this, cachedHeaders, this.Method); } }