Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / HttpContextServiceHost.cs / 1305376 / HttpContextServiceHost.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// Provides an HttpContext-based implementation. // // // @owner [....] //--------------------------------------------------------------------- namespace System.Data.Services { #region Namespaces. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.ServiceModel; using System.ServiceModel.Web; #endregion Namespaces. ////// Provides access to the environment for a DataService, including information about the current request, based /// on the current WebOperationContext. /// internal class HttpContextServiceHost : IDataServiceHost2 { #region Private fields. ///Message sent to server. private readonly Stream incomingMessageBody; ///The WCF-based operation context. private readonly WebOperationContext operationContext; ///Whether an error was found when processing this request. private bool errorFound; ///Gets the absolute URI to the resource upon which to apply the request. private Uri absoluteRequestUri; ///Gets the absolute URI to the service. private Uri absoluteServiceUri; #endregion Private fields. #region Constructors. ////// Initializes a new System.Data.Services.HttpContextServiceHost instance. /// /// Incoming message body to process. internal HttpContextServiceHost(Stream messageBody) { // We capture the current context at initialization time rather // than accessing it repeatedly. this.incomingMessageBody = messageBody; this.operationContext = WebOperationContext.Current; if (this.operationContext == null) { throw new InvalidOperationException(Strings.HttpContextServiceHost_WebOperationContextCurrentMissing); } } #endregion Constructors. #region Properties. ////// Gets the character set encoding that the client requested, /// possibly null. /// string IDataServiceHost.RequestAcceptCharSet { get { // Returns a string that contains the comma-separated list of values // associated with the specified key, if found; otherwise, null. return this.operationContext.IncomingRequest.Headers[HttpRequestHeader.AcceptCharset]; } } ///Gets or sets the HTTP MIME type of the output stream. string IDataServiceHost.ResponseContentType { get { return this.operationContext.OutgoingResponse.ContentType; } set { this.operationContext.OutgoingResponse.ContentType = value; } } ///Gets the HTTP MIME type of the input stream. string IDataServiceHost.RequestContentType { get { return this.operationContext.IncomingRequest.ContentType; } } ////// Gets a comma-separated list of client-supported MIME Accept types. /// string IDataServiceHost.RequestAccept { get { return this.operationContext.IncomingRequest.Accept; } } ////// Gets the HTTP data transfer method (such as GET, POST, or HEAD) used by the client. /// string IDataServiceHost.RequestHttpMethod { get { string result; string[] methodValues = this.operationContext.IncomingRequest.Headers.GetValues(XmlConstants.HttpXMethod); if (methodValues == null || methodValues.Length == 0) { result = this.operationContext.IncomingRequest.Method; } else if (methodValues.Length == 1) { result = methodValues[0]; if (this.operationContext.IncomingRequest.Method != XmlConstants.HttpMethodPost) { throw DataServiceException.CreateBadRequestError(Strings.HttpContextServiceHost_XMethodNotUsingPost); } if (result != XmlConstants.HttpMethodDelete && result != XmlConstants.HttpMethodPut && result != XmlConstants.HttpMethodMerge) { throw DataServiceException.CreateBadRequestError(Strings.HttpContextServiceHost_XMethodIncorrectValue(result)); } } else { throw DataServiceException.CreateBadRequestError(Strings.HttpContextServiceHost_XMethodIncorrectCount(methodValues.Length)); } return result; } } ///Gets the value of the If-Match header from the request made string IDataServiceHost.RequestIfMatch { get { return this.operationContext.IncomingRequest.Headers[HttpRequestHeader.IfMatch]; } } ///Gets the value of the If-None-Match header from the request made string IDataServiceHost.RequestIfNoneMatch { get { return this.operationContext.IncomingRequest.Headers[HttpRequestHeader.IfNoneMatch]; } } ///Gets the value for the MaxDataServiceVersion request header. string IDataServiceHost.RequestMaxVersion { get { return this.operationContext.IncomingRequest.Headers[XmlConstants.HttpMaxDataServiceVersion]; } } ///Gets the value for the DataServiceVersion request header. string IDataServiceHost.RequestVersion { get { return this.operationContext.IncomingRequest.Headers[XmlConstants.HttpDataServiceVersion]; } } ///Gets the absolute URI to the resource upon which to apply the request. Uri IDataServiceHost.AbsoluteRequestUri { get { if (this.absoluteRequestUri == null) { object property; if (OperationContext.Current.IncomingMessageProperties.TryGetValue(XmlConstants.MicrosoftDataServicesRequestUri, out property)) { this.absoluteRequestUri = property as Uri; if (this.absoluteRequestUri == null) { throw new InvalidOperationException(Strings.HttpContextServiceHost_IncomingMessagePropertyMustBeValidUriInstance(XmlConstants.MicrosoftDataServicesRequestUri)); } } if (this.absoluteRequestUri == null) { UriTemplateMatch match = this.operationContext.IncomingRequest.UriTemplateMatch; this.absoluteRequestUri = WebUtil.ApplyHostHeader(match.RequestUri, this.HostHeader); } } return this.absoluteRequestUri; } } ///Gets or sets the Cache-Control header on the response. string IDataServiceHost.ResponseCacheControl { get { return this.operationContext.OutgoingResponse.Headers[HttpResponseHeader.CacheControl]; } set { this.operationContext.OutgoingResponse.Headers[HttpResponseHeader.CacheControl] = value; } } ///Gets/Sets the value of the ETag header on the outgoing response string IDataServiceHost.ResponseETag { get { return this.operationContext.OutgoingResponse.ETag; } set { this.operationContext.OutgoingResponse.ETag = value; } } ///Gets or sets the Location header on the response. string IDataServiceHost.ResponseLocation { get { return this.operationContext.OutgoingResponse.Headers[HttpResponseHeader.Location]; } set { this.operationContext.OutgoingResponse.Headers[HttpResponseHeader.Location] = value; } } ////// Gets/Sets the status code for the request made. /// int IDataServiceHost.ResponseStatusCode { get { return (int) this.operationContext.OutgoingResponse.StatusCode; } set { HttpStatusCode statusCode = (HttpStatusCode)value; this.operationContext.OutgoingResponse.StatusCode = statusCode; // Some status codes such as NoContent or NotModified MUST NOT include a message-body in the response. // We need to set SupressEntityBody to true so that in the case of chuncked encoding WCF won't write // a '0' in the message body to indicate there is no more content. // Note that not setting this will result in a HTTP Protocol Violation exception when chuncked encoding is on. this.operationContext.OutgoingResponse.SuppressEntityBody = MustNotReturnMessageBody(statusCode); } } ////// Gets the Stream IDataServiceHost.ResponseStream { get { // The ResponseStream is not directly accessible - this would // prevent WCF from streaming results back. For the WCF host, // a Message subclass should write directly in the OnBodyWrite // method. throw Error.NotSupported(); } } ///to be written to send a response /// to the client. /// Gets or sets the value for the DataServiceVersion response header. string IDataServiceHost.ResponseVersion { get { return this.operationContext.OutgoingResponse.Headers[XmlConstants.HttpDataServiceVersion]; } set { this.operationContext.OutgoingResponse.Headers[XmlConstants.HttpDataServiceVersion] = value; } } ///Gets the absolute URI to the service. Uri IDataServiceHost.AbsoluteServiceUri { get { if (this.absoluteServiceUri == null) { object property; if (OperationContext.Current.IncomingMessageProperties.TryGetValue(XmlConstants.MicrosoftDataServicesRootUri, out property)) { this.absoluteServiceUri = property as Uri; if (this.absoluteServiceUri == null) { throw new InvalidOperationException(Strings.HttpContextServiceHost_IncomingMessagePropertyMustBeValidUriInstance(XmlConstants.MicrosoftDataServicesRootUri)); } } if (this.absoluteServiceUri == null) { UriTemplateMatch match = this.operationContext.IncomingRequest.UriTemplateMatch; // We never want to consider the last segment of the base URI a 'document' type // of segment to be replaced, ie, http://foo/svc.svc should never remove svc.svc // from the path. this.absoluteServiceUri = WebUtil.ApplyHostHeader(match.BaseUri, this.HostHeader); } if (!String.IsNullOrEmpty(this.absoluteServiceUri.Fragment)) { throw new InvalidOperationException(Strings.HttpContextServiceHost_IncomingTemplateMatchFragment(this.absoluteServiceUri)); } if (!String.IsNullOrEmpty(this.absoluteServiceUri.Query)) { throw new InvalidOperationException(Strings.HttpContextServiceHost_IncomingTemplateMatchQuery(this.absoluteServiceUri)); } this.absoluteServiceUri = WebUtil.EnsureLastSegmentEmpty(this.absoluteServiceUri); } return this.absoluteServiceUri; } } ////// Gets the Stream IDataServiceHost.RequestStream { [DebuggerStepThrough] get { return this.incomingMessageBody; } } #region IDataServiceHost2 Properties ///from which the request data can be read from /// to the client. /// Dictionary of all request headers from the host. WebHeaderCollection IDataServiceHost2.RequestHeaders { [DebuggerStepThrough] get { return this.operationContext.IncomingRequest.Headers; } } ///Enumerates all response headers that has been set. WebHeaderCollection IDataServiceHost2.ResponseHeaders { [DebuggerStepThrough] get { return this.operationContext.OutgoingResponse.Headers; } } #endregion IDataServiceHost2 Properties ///Whether an error was found when processing this request. internal bool ErrorFound { get { return this.errorFound; } } ///The value for the Host header in the request, possibly null. private string HostHeader { get { return this.operationContext.IncomingRequest.Headers[HttpRequestHeader.Host]; } } #endregion Properties. #region Methods. ///Gets the value for the specified item in the request query string. /// Item to return. ////// The value for the specified item in the request query string; /// null if string IDataServiceHost.GetQueryStringItem(string item) { Debug.Assert(item != null, "item != null"); Debug.Assert(item.Trim() == item, "item.Trim() == item - otherwise, there are leading/trailing spaces in the name"); System.Collections.Specialized.NameValueCollection collection = this.operationContext.IncomingRequest.UriTemplateMatch.QueryParameters; string[] values = collection.GetValues(item); if (values == null || values.Length == 0) { // Do a scan of arguments ignoring whitespace (SQLBUDT #555944). string keyFound = null; foreach (string key in collection.Keys) { if (key != null && StringComparer.OrdinalIgnoreCase.Equals(key.Trim(), item)) { if (keyFound != null) { throw DataServiceException.CreateBadRequestError(Strings.HttpContextServiceHost_AmbiguousItemName(item, keyFound, key)); } keyFound = key; values = collection.GetValues(key); } } if (values == null || values.Length == 0) { return null; } } Debug.Assert(values != null && values.Length > 0, "values != null && values.Length > 0 - otherwise we should have returned already"); if (values.Length == 1) { return values[0]; } else { throw DataServiceException.CreateSyntaxError(); } } ///is not found. /// /// Method to handle a data service exception during processing. /// /// Exception handling description. void IDataServiceHost.ProcessException(HandleExceptionArgs args) { Debug.Assert(this.operationContext != null, "this.operationContext != null"); this.errorFound = true; if (!args.ResponseWritten) { ((IDataServiceHost)this).ResponseStatusCode = args.ResponseStatusCode; ((IDataServiceHost)this).ResponseContentType = args.ResponseContentType; if (args.ResponseAllowHeader != null) { this.operationContext.OutgoingResponse.Headers[HttpResponseHeader.Allow] = args.ResponseAllowHeader; } } } ///Verifies that query parameters are valid. internal void VerifyQueryParameters() { HashSetnamesFound = new HashSet (StringComparer.Ordinal); System.Collections.Specialized.NameValueCollection collection = this.operationContext.IncomingRequest.UriTemplateMatch.QueryParameters; for (int i = 0; i < collection.Count; i++) { string name = collection.GetKey(i); if (name == null) { // These are values of the form a&b&c, without '='. We just make sure they aren't system // values at all. string[] values = collection.GetValues(i); if (values != null) { for (int j = 0; j < values.Length; j++) { string value = values[j].Trim(); if (value.Length > 0 && value[0] == '$') { throw DataServiceException.CreateBadRequestError( Strings.HttpContextServiceHost_QueryParameterMustBeSpecifiedOnce(value)); } } } continue; } name = name.Trim(); if (!namesFound.Add(name)) { throw DataServiceException.CreateBadRequestError( Strings.HttpContextServiceHost_QueryParameterMustBeSpecifiedOnce(name)); } if (name.Length > 0 && name[0] == '$') { if (name != XmlConstants.HttpQueryStringExpand && name != XmlConstants.HttpQueryStringFilter && name != XmlConstants.HttpQueryStringOrderBy && name != XmlConstants.HttpQueryStringSkip && name != XmlConstants.HttpQueryStringSkipToken && name != XmlConstants.HttpQueryStringInlineCount && name != XmlConstants.HttpQueryStringTop && name != XmlConstants.HttpQueryStringSelect) { throw DataServiceException.CreateBadRequestError( Strings.HttpContextServiceHost_UnknownQueryParameter(name)); } string[] values = collection.GetValues(i); if (values == null || values.Length != 1) { throw DataServiceException.CreateBadRequestError( Strings.HttpContextServiceHost_QueryParameterMustBeSpecifiedOnce(name)); } } } } /// /// Check to see if the given status code expects an empty message-body. /// /// Http status code ///True if the message-body must be empty for the given status code, false otherwise. private static bool MustNotReturnMessageBody(HttpStatusCode statusCode) { // Both 204 and 304 must not include a message-body in the response. switch (statusCode) { case HttpStatusCode.NoContent: // 204 case HttpStatusCode.ResetContent: // 205 case HttpStatusCode.NotModified: // 304 return true; default: return false; } } #endregion Methods. } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InvalidWMPVersionException.cs
- SeekableReadStream.cs
- Common.cs
- ListViewItemMouseHoverEvent.cs
- PinnedBufferMemoryStream.cs
- CancellationToken.cs
- DynamicDataResources.Designer.cs
- WrapPanel.cs
- GenericUriParser.cs
- PartialList.cs
- LocalValueEnumerator.cs
- OrderedDictionaryStateHelper.cs
- CrossAppDomainChannel.cs
- _UriTypeConverter.cs
- Misc.cs
- SqlTypeConverter.cs
- RecipientInfo.cs
- ExpressionBindingCollection.cs
- Vector3dCollection.cs
- DateTimeStorage.cs
- SplineKeyFrames.cs
- XmlSchemaElement.cs
- TextSearch.cs
- CollectionChangedEventManager.cs
- ProcessRequestArgs.cs
- TripleDESCryptoServiceProvider.cs
- HitTestFilterBehavior.cs
- IfAction.cs
- DeclarativeCatalogPart.cs
- AppSecurityManager.cs
- DecoderBestFitFallback.cs
- CommittableTransaction.cs
- InstalledFontCollection.cs
- BaseProcessor.cs
- DataGridItem.cs
- DataGridPagerStyle.cs
- UserControl.cs
- TraversalRequest.cs
- ResXFileRef.cs
- ThemeableAttribute.cs
- ellipse.cs
- ContainerActivationHelper.cs
- ComponentFactoryHelpers.cs
- FlowDocumentPaginator.cs
- DbBuffer.cs
- ClrPerspective.cs
- KeyFrames.cs
- Errors.cs
- TransformDescriptor.cs
- FileNotFoundException.cs
- ReturnValue.cs
- DataGridToolTip.cs
- remotingproxy.cs
- HitTestParameters3D.cs
- ToolStripDesignerAvailabilityAttribute.cs
- ElementNotEnabledException.cs
- TypedOperationInfo.cs
- ResourceExpression.cs
- _NegotiateClient.cs
- PointCollectionConverter.cs
- SubMenuStyle.cs
- DocumentApplicationJournalEntry.cs
- PerformanceCounterPermissionEntry.cs
- AuthorizationRuleCollection.cs
- CapabilitiesUse.cs
- DefaultEventAttribute.cs
- ApplicationSecurityManager.cs
- SplitContainer.cs
- FileDialogCustomPlacesCollection.cs
- DbConnectionPool.cs
- DataGridViewRowHeightInfoPushedEventArgs.cs
- StateMachineSubscription.cs
- FilterInvalidBodyAccessException.cs
- DataGrid.cs
- SqlCacheDependencySection.cs
- SafeUserTokenHandle.cs
- ImageMap.cs
- BamlResourceSerializer.cs
- SafeRegistryHandle.cs
- RowType.cs
- RectAnimationBase.cs
- UrlMappingsSection.cs
- Control.cs
- BinaryReader.cs
- AttachedPropertyInfo.cs
- PropertyValueUIItem.cs
- EntityDataReader.cs
- Types.cs
- RemoteCryptoDecryptRequest.cs
- TreeViewImageIndexConverter.cs
- DesignerOptionService.cs
- RetriableClipboard.cs
- DocumentXmlWriter.cs
- TableLayoutPanelBehavior.cs
- DataGridItem.cs
- BamlLocalizableResource.cs
- ButtonBaseAutomationPeer.cs
- DataGridColumnCollectionEditor.cs
- PostBackTrigger.cs
- SpellerHighlightLayer.cs