/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="headers">The headers.</param>
 /// <param name="statusCode">The status code.</param>
 /// <param name="getResponseStream">A function returning the response stream.</param>
 /// <param name="underlyingResponseMessage">The underlying response message that should be disposed together with this instance.</param>
 internal HttpWebResponseMessage(HeaderCollection headers, int statusCode, Func <Stream> getResponseStream, IODataResponseMessage underlyingResponseMessage)
     : this(headers, statusCode, getResponseStream)
 {
     this.underlyingResponseMessage = underlyingResponseMessage;
 }
Exemple #2
0
        /// <summary>
        /// Synchronizely get the query set count from the server by executing the $count=value query
        /// </summary>
        /// <param name="context">The context</param>
        /// <returns>The server side count of the query set</returns>
        internal long GetQuerySetCount(DataServiceContext context)
        {
            Debug.Assert(null != context, "context is null");
            Version requestVersion = this.QueryComponents(context.Model).Version;

            if (requestVersion == null || requestVersion.Major < 2)
            {
                // minimum DSV for $count is V2.
                requestVersion = Util.DataServiceVersion2;
            }

            QueryResult               response       = null;
            QueryComponents           qc             = this.QueryComponents(context.Model);
            Uri                       requestUri     = qc.Uri;
            DataServiceRequest <long> serviceRequest = new DataServiceRequest <long>(requestUri, qc, null);

            HeaderCollection headers = new HeaderCollection();

            // Validate and set the request DSV header
            headers.SetRequestVersion(requestVersion, context.MaxProtocolVersionAsVersion);
            context.Format.SetRequestAcceptHeaderForCount(headers);

            string httpMethod = XmlConstants.HttpMethodGet;
            ODataRequestMessageWrapper request = context.CreateODataRequestMessage(
                context.CreateRequestArgsAndFireBuildingRequest(httpMethod, requestUri, headers, context.HttpStack, null /*descriptor*/),
                new string[] { XmlConstants.HttpRequestAccept } /*headersToReset*/,
                null /*descriptor*/);

            response = new QueryResult(this, Util.ExecuteMethodName, serviceRequest, request, new RequestInfo(context), null, null);
            response.AllowDirectNetworkStreamReading = context.AllowDirectNetworkStreamReading;

            IODataResponseMessage responseMessage = null;

            try
            {
                responseMessage = response.ExecuteQuery();
                if (HttpStatusCode.NoContent != response.StatusCode)
                {
                    StreamReader sr = new StreamReader(response.GetResponseStream());
                    long         r  = -1;

                    try
                    {
                        r = XmlConvert.ToInt64(sr.ReadToEnd());
                    }
                    finally
                    {
                        sr.Close();
                    }

                    return(r);
                }
                else
                {
                    throw new DataServiceQueryException(Strings.DataServiceRequest_FailGetCount, response.Failure);
                }
            }
            catch (InvalidOperationException ex)
            {
                QueryOperationResponse operationResponse = null;
                operationResponse = response.GetResponse <long>(MaterializeAtom.EmptyResults);
                if (null != operationResponse)
                {
                    operationResponse.Error = ex;
                    throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse);
                }

                throw;
            }
            finally
            {
                WebUtil.DisposeMessage(responseMessage);
            }
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        /// <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);
            }
        }
Exemple #5
0
        /// <summary>
        /// The reason for adding this method is that we have seen a couple of asserts that we were not able to figure out why they are getting fired.
        /// So added this method which returns the current headers as well as cached headers as string and we display that in the assert message.
        /// </summary>
        /// <param name="currentHeaders">current header values.</param>
        /// <param name="cachedHeaders">cached header values.</param>
        /// <returns>returns a string which contains both current and cached header names.</returns>
        private static string GetHeaderValues(IEnumerable <KeyValuePair <string, string> > currentHeaders, HeaderCollection cachedHeaders)
        {
            StringBuilder sb        = new StringBuilder();
            string        separator = String.Empty;

            sb.Append("Current Headers: ");
            foreach (var header in currentHeaders)
            {
                sb.Append(separator);
                sb.Append(header.Key);
                separator = ", ";
            }

            sb.Append(". Headers fired in SendingRequest: ");
            separator = String.Empty;
            foreach (string name in cachedHeaders.HeaderNames)
            {
                sb.Append(separator);
                sb.Append(name);
                separator = ", ";
            }

            return(sb.ToString());
        }
 /// <summary>
 /// Sets the value of the Accept header to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeader(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationAtomOrXml, false));
 }
Exemple #7
0
        /// <summary>
        /// Set the header values on the request.
        /// </summary>
        /// <param name="requestMessage">IODataRequestMessage instance containing all the headers.</param>
        /// <param name="cachedHeaders">Dictionary of cached headers.</param>
        /// <param name="effectiveHttpMethod">The Effective http method.</param>
        private static void SetHeaderValues(HttpWebRequestMessage requestMessage, HeaderCollection cachedHeaders, string effectiveHttpMethod)
        {
            // DevNote(shank): We used to set request.AllowWriteStreamBuffering to true here. This is now removed
            //                 as it prevents customers from enabling HTTP streaming by setting it to false in the
            //                 SendingRequest event. This is because this method is called twice by CreateGetRequest(),
            //                 before *and* after the SendingRequest event (see DevNote in CreateGetRequest()).
            //                 We also do *not* set it to false by default for media resource requests. Enabling
            //                 streaming requires additional actions to be performed by the customer, e.g., sending
            //                 chunks if content-length is not specified, and pre-authenticating with a HEAD request.
#if !ASTORIA_LIGHT && !PORTABLELIB
            bool removeXMethod = true;
#endif
            Debug.Assert(requestMessage.requestInfo != null, "This method is called from FireSendingRequest. Hence requestInfo should never be null.");
            HttpWebRequest request     = requestMessage.httpRequest;
            string         method      = requestMessage.Method;
            string         contentType = null;
            cachedHeaders.TryGetHeader(XmlConstants.HttpContentType, out contentType);

            if (string.CompareOrdinal(effectiveHttpMethod, XmlConstants.HttpMethodGet) != 0)
            {
                if (string.CompareOrdinal(effectiveHttpMethod, XmlConstants.HttpMethodDelete) == 0)
                {
                    // In V2, we always use to over-write content type after sendingRequest event has been called.
                    // So doing the same for delete requests.
                    // TODO: no need to override this if it was set in building request; just override it was changed elsewhere?
                    Debug.Assert(String.IsNullOrEmpty(contentType), "Content-Type must not be specified for delete operation");
                    request.ContentType = null;
                    SetHttpWebRequestContentLength(request, 0);
                }
                else
                {
                    Debug.Assert(!String.IsNullOrEmpty(contentType), "Content-Type must be specified for non get and non delete operations");
                    request.ContentType = contentType;
                }

                if (requestMessage.requestInfo.UsePostTunneling && (string.CompareOrdinal(effectiveHttpMethod, XmlConstants.HttpMethodPost) != 0))
                {
                    Debug.Assert(effectiveHttpMethod != null, "expected an effectiveHttpMethod");
                    request.Headers[XmlConstants.HttpXMethod] = effectiveHttpMethod;
                    method = XmlConstants.HttpMethodPost;
#if !ASTORIA_LIGHT && !PORTABLELIB
                    removeXMethod = false;
#endif
                }
            }

            // We cannot assert that the content type for GET request is null, since in some scenarios (e.g. GetReadStream),
            // the user can pass the content type in the API and they can set the content type to something. In those
            // scenarios, we set the content type as specified by the user and not check for anything.
#if !ASTORIA_LIGHT && !PORTABLELIB
            // Removing the If-Match header so that if it was accidently written when it should not
            // have, it will get removed after the event. The correct value will be written again
            // when reseting the headers.
            request.Headers.Remove(HttpRequestHeader.IfMatch);

            // alternate HttpXMethod header doesn't work
            if (removeXMethod)
            {
                request.Headers.Remove(XmlConstants.HttpXMethod);
            }
#endif
            request.Method = method;

            // Reset the list of headers, if any
            if (requestMessage.headersToReset != null)
            {
                foreach (string headerName in requestMessage.headersToReset)
                {
#if ASTORIA_LIGHT || PORTABLELIB
                    // Ignoring content length header since its not supported in silverlight
                    if (string.Equals(headerName, XmlConstants.HttpContentLength, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
#endif
                    HttpWebRequestMessage.SetHeaderValue(request, headerName, cachedHeaders.GetHeader(headerName));
                }
            }
        }
 /// <summary>
 /// Sets the value of the ContentType header on the specified links request to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">Dictionary of request headers.</param>
 internal void SetRequestContentTypeForLinks(HeaderCollection headers)
 {
     this.SetRequestContentTypeHeader(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationXml, false));
 }
Exemple #9
0
 /// <summary>
 /// Asks the context to Fire the BuildingRequest event and get RequestMessageArgs.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <returns>A new RequestMessageArgs object for building the request message.</returns>
 internal BuildingRequestEventArgs CreateRequestArgsAndFireBuildingRequest(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor)
 {
     return(this.Context.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, httpStack, descriptor));
 }
 /// <summary>
 /// Sets the value of the Accept header for a count request (will set it to 'multipart/mixed').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForBatch(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, MimeMultiPartMixed);
 }
 /// <summary>
 /// Sets the value of the  Content-Type header a request with operation parameters to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">Dictionary of request headers.</param>
 internal void SetRequestContentTypeForOperationParameters(HeaderCollection headers)
 {
     // Note: There has never been an atom or xml format for parameters, so atom really means V3 default here.
     this.SetRequestContentTypeHeader(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationJsonODataVerbose, false));
 }
 /// <summary>
 /// Sets the value of the Accept header for a count request (will set it to 'text/plain').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForCount(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, XmlConstants.MimeTextPlain);
 }
 /// <summary>
 /// Sets the value of the Accept header for a stream request (will set it to '*/*').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForStream(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, XmlConstants.MimeAny);
 }
 /// <summary>
 /// Sets the value of the Accept header for a query.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 /// <param name="components">The query components for the request.</param>
 internal void SetRequestAcceptHeaderForQuery(HeaderCollection headers, QueryComponents components)
 {
     this.SetAcceptHeaderAndCharset(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationAtomOrXml, components.HasSelectQueryOption));
 }
Exemple #15
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 internal OperationResponse(HeaderCollection headers)
 {
     Debug.Assert(null != headers, "null headers");
     this.headers = headers;
 }
Exemple #16
0
 /// <summary>Initializes a new instance of the <see cref="T:System.Data.Services.Client.ChangeOperationResponse" /> class. </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="descriptor">response object containing information about resources that got changed.</param>
 internal ChangeOperationResponse(HeaderCollection headers, Descriptor descriptor)
     : base(headers)
 {
     Debug.Assert(descriptor != null, "descriptor != null");
     this.descriptor = descriptor;
 }
Exemple #17
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers, query, results)
 {
 }
Exemple #18
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers)
 {
     this.query   = query;
     this.results = results;
 }