Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx35 / System.ServiceModel.Web / System / ServiceModel / Web / IncomingWebRequestContext.cs / 1305376 / IncomingWebRequestContext.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- #pragma warning disable 1634, 1691 namespace System.ServiceModel.Web { using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Net; using System.Net.Mime; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Channels; using System.Collections.ObjectModel; public class IncomingWebRequestContext { static readonly string HttpGetMethod = "GET"; static readonly string HttpHeadMethod = "HEAD"; static readonly string HttpPutMethod = "PUT"; static readonly string HttpPostMethod = "POST"; static readonly string HttpDeleteMethod = "DELETE"; CollectioncachedAcceptHeaderElements; string acceptHeaderWhenHeaderElementsCached; internal const string UriTemplateMatchResultsPropertyName = "UriTemplateMatchResults"; OperationContext operationContext; internal IncomingWebRequestContext(OperationContext operationContext) { Fx.Assert(operationContext != null, "operationContext is null"); this.operationContext = operationContext; } public string Accept { get { return EnsureMessageProperty().Headers[HttpRequestHeader.Accept]; } } public long ContentLength { get { return long.Parse(this.EnsureMessageProperty().Headers[HttpRequestHeader.ContentLength], CultureInfo.InvariantCulture); } } public string ContentType { get { return this.EnsureMessageProperty().Headers[HttpRequestHeader.ContentType]; } } public IEnumerable IfMatch { get { string ifMatchHeader = MessageProperty.Headers[HttpRequestHeader.IfMatch]; return (string.IsNullOrEmpty(ifMatchHeader)) ? null : QuoteAwareStringSplit(ifMatchHeader); } } public IEnumerable IfNoneMatch { get { string ifNoneMatchHeader = MessageProperty.Headers[HttpRequestHeader.IfNoneMatch]; return (string.IsNullOrEmpty(ifNoneMatchHeader)) ? null : QuoteAwareStringSplit(ifNoneMatchHeader); } } public DateTime? IfModifiedSince { get { string dateTime = this.MessageProperty.Headers[HttpRequestHeader.IfModifiedSince]; if (!string.IsNullOrEmpty(dateTime)) { DateTime parsedDateTime; if (HttpDateParse.ParseHttpDate(dateTime, out parsedDateTime)) { return parsedDateTime; } } return null; } } public DateTime? IfUnmodifiedSince { get { string dateTime = this.MessageProperty.Headers[HttpRequestHeader.IfUnmodifiedSince]; if (!string.IsNullOrEmpty(dateTime)) { DateTime parsedDateTime; if (HttpDateParse.ParseHttpDate(dateTime, out parsedDateTime)) { return parsedDateTime; } } return null; } } public WebHeaderCollection Headers { get { return this.EnsureMessageProperty().Headers; } } public string Method { get { return this.EnsureMessageProperty().Method; } } public UriTemplateMatch UriTemplateMatch { get { if (this.operationContext.IncomingMessageProperties.ContainsKey(UriTemplateMatchResultsPropertyName)) { return this.operationContext.IncomingMessageProperties[UriTemplateMatchResultsPropertyName] as UriTemplateMatch; } else { return null; } } set { this.operationContext.IncomingMessageProperties[UriTemplateMatchResultsPropertyName] = value; } } public string UserAgent { get { return this.EnsureMessageProperty().Headers[HttpRequestHeader.UserAgent]; } } HttpRequestMessageProperty MessageProperty { get { if (operationContext.IncomingMessageProperties == null) { return null; } if (!operationContext.IncomingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name)) { return null; } return operationContext.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; } } public void CheckConditionalRetrieve(string entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtagFromString(entityTag); CheckConditionalRetrieveWithValidatedEtag(validEtag); } public void CheckConditionalRetrieve(int entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalRetrieveWithValidatedEtag(validEtag); } public void CheckConditionalRetrieve(long entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalRetrieveWithValidatedEtag(validEtag); } public void CheckConditionalRetrieve(Guid entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalRetrieveWithValidatedEtag(validEtag); } public void CheckConditionalRetrieve(DateTime lastModified) { if (!string.Equals(this.Method, IncomingWebRequestContext.HttpGetMethod, StringComparison.OrdinalIgnoreCase) && !string.Equals(this.Method, IncomingWebRequestContext.HttpHeadMethod, StringComparison.OrdinalIgnoreCase)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR2.GetString(SR2.ConditionalRetrieveGetAndHeadOnly, this.Method))); } DateTime? ifModifiedSince = this.IfModifiedSince; if (ifModifiedSince.HasValue) { long ticksDifference = lastModified.ToUniversalTime().Ticks - ifModifiedSince.Value.ToUniversalTime().Ticks; if (ticksDifference < TimeSpan.TicksPerSecond) { WebOperationContext.Current.OutgoingResponse.LastModified = lastModified; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.NotModified)); } } } public void CheckConditionalUpdate(string entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtagFromString(entityTag); CheckConditionalUpdateWithValidatedEtag(validEtag); } public void CheckConditionalUpdate(int entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalUpdateWithValidatedEtag(validEtag); } public void CheckConditionalUpdate(long entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalUpdateWithValidatedEtag(validEtag); } public void CheckConditionalUpdate(Guid entityTag) { string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); CheckConditionalUpdateWithValidatedEtag(validEtag); } public Collection GetAcceptHeaderElements() { string acceptHeader = this.Accept; if (cachedAcceptHeaderElements == null || (!string.Equals(acceptHeaderWhenHeaderElementsCached, acceptHeader, StringComparison.OrdinalIgnoreCase))) { if (string.IsNullOrEmpty(acceptHeader)) { cachedAcceptHeaderElements = new Collection (); acceptHeaderWhenHeaderElementsCached = acceptHeader; } else { List contentTypeList = new List (); int offset = 0; while (true) { string nextItem = QuoteAwareSubString(acceptHeader, ref offset); if (nextItem == null) { break; } ContentType contentType = GetContentTypeOrNull(nextItem); if (contentType != null) { contentTypeList.Add(contentType); } } contentTypeList.Sort(new AcceptHeaderElementComparer()); cachedAcceptHeaderElements = new Collection (contentTypeList); acceptHeaderWhenHeaderElementsCached = acceptHeader; } } return cachedAcceptHeaderElements; } HttpRequestMessageProperty EnsureMessageProperty() { if (this.MessageProperty == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR2.GetString(SR2.HttpContextNoIncomingMessageProperty, typeof(HttpRequestMessageProperty).Name))); } return this.MessageProperty; } // This method extracts substrings from an HTTP header starting at the offset // and up until the next comma in the header. The sub string extraction is // quote aware such that commas inside quoted-strings are ignored. On return, // offset points to the next char beyond the comma of the substring returned // and may point beyond the length of the header. internal static string QuoteAwareSubString(string header, ref int offset) { // this method will filter out empty-string and white-space-only items in // the header. For example "x,,y" and "x, ,y" would result in just "x" and "y" // substrings being returned. if (string.IsNullOrEmpty(header) || offset >= header.Length) { return null; } int startIndex = (offset > 0) ? offset : 0; // trim whitespace and commas from the begining of the item while (char.IsWhiteSpace(header[startIndex]) || header[startIndex] == ',') { startIndex++; if (startIndex >= header.Length) { return null; } } int endIndex = startIndex; bool insideQuotes = false; while (endIndex < header.Length) { if (header[endIndex] == '\"' && (!insideQuotes || endIndex == 0 || header[endIndex - 1] != '\\')) { insideQuotes = !insideQuotes; } else if (header[endIndex] == ',' && !insideQuotes) { break; } endIndex++; } offset = endIndex + 1; // trim whitespace from the end of the item; the substring is guaranteed to // have at least one non-whitespace character while (char.IsWhiteSpace(header[endIndex - 1])) { endIndex--; } return header.Substring(startIndex, endIndex - startIndex); } internal static List QuoteAwareStringSplit(string header) { List subStrings = new List (); int offset = 0; while (true) { string subString = QuoteAwareSubString(header, ref offset); if (subString == null) { break; } subStrings.Add(subString); } return subStrings; } internal static ContentType GetContentType(string contentType) { string contentTypeTrimmed = contentType.Trim(); if (!string.IsNullOrEmpty(contentTypeTrimmed)) { return GetContentTypeOrNull(contentTypeTrimmed); } return null; } static ContentType GetContentTypeOrNull(string contentType) { try { Fx.Assert(contentType == contentType.Trim(), "The ContentType input argument should already be trimmed."); Fx.Assert(!string.IsNullOrEmpty(contentType), "The ContentType input argument should not be null or empty."); ContentType contentTypeToReturn = new ContentType(contentType); // Need to check for "*/ " because the ContentType constructor doesn't catch this string[] typeAndSubType = contentTypeToReturn.MediaType.Split('/'); Fx.Assert(typeAndSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); if (typeAndSubType[0][0] == '*' && typeAndSubType[0].Length == 1 && !(typeAndSubType[1][0] == '*' && typeAndSubType[1].Length == 1)) { // // throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FormatException( // SR2.GetString(SR2.InvalidContentType, contentType))); return null; } return contentTypeToReturn; } catch (FormatException e) { // Return null to indicate that the content type creation failed System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning); } return null; } void CheckConditionalRetrieveWithValidatedEtag(string entityTag) { if (!string.Equals(this.Method, IncomingWebRequestContext.HttpGetMethod, StringComparison.OrdinalIgnoreCase) && !string.Equals(this.Method, IncomingWebRequestContext.HttpHeadMethod, StringComparison.OrdinalIgnoreCase)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR2.GetString(SR2.ConditionalRetrieveGetAndHeadOnly, this.Method))); } if (!string.IsNullOrEmpty(entityTag)) { string entityTagHeader = this.Headers[HttpRequestHeader.IfNoneMatch]; if (!string.IsNullOrEmpty(entityTagHeader)) { if (IsWildCardCharacter(entityTagHeader) || DoesHeaderContainEtag(entityTagHeader, entityTag)) { // set response entityTag directly because it has already been validated WebOperationContext.Current.OutgoingResponse.ETag = entityTag; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.NotModified)); } } } } void CheckConditionalUpdateWithValidatedEtag(string entityTag) { bool isPutMethod = string.Equals(this.Method, IncomingWebRequestContext.HttpPutMethod, StringComparison.OrdinalIgnoreCase); if (!isPutMethod && !string.Equals(this.Method, IncomingWebRequestContext.HttpPostMethod, StringComparison.OrdinalIgnoreCase) && !string.Equals(this.Method, IncomingWebRequestContext.HttpDeleteMethod, StringComparison.OrdinalIgnoreCase)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR2.GetString(SR2.ConditionalUpdatePutPostAndDeleteOnly, this.Method))); } string headerOfInterest; // if the current entityTag is null then the resource doesn't currently exist and the // a PUT request should only succeed if If-None-Match equals '*'. if (isPutMethod && string.IsNullOrEmpty(entityTag)) { headerOfInterest = this.Headers[HttpRequestHeader.IfNoneMatch]; if (string.IsNullOrEmpty(headerOfInterest) || !IsWildCardCharacter(headerOfInterest)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.PreconditionFailed)); } } else { // all remaining cases are with an If-Match header headerOfInterest = this.Headers[HttpRequestHeader.IfMatch]; if (string.IsNullOrEmpty(headerOfInterest) || (!IsWildCardCharacter(headerOfInterest) && !DoesHeaderContainEtag(headerOfInterest, entityTag))) { // set response entityTag directly because it has already been validated WebOperationContext.Current.OutgoingResponse.ETag = entityTag; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.PreconditionFailed)); } } } static bool DoesHeaderContainEtag(string header, string entityTag) { int offset = 0; while (true) { string nextEntityTag = IncomingWebRequestContext.QuoteAwareSubString(header, ref offset); if (nextEntityTag == null) { break; } if (string.Equals(nextEntityTag, entityTag, StringComparison.Ordinal)) { return true; } } return false; } static bool IsWildCardCharacter(string header) { return (header.Trim() == "*"); } class AcceptHeaderElementComparer : IComparer { static NumberStyles numberStyles = NumberStyles.AllowDecimalPoint; public int Compare(ContentType x, ContentType y) { string[] xTypeSubType = x.MediaType.Split('/'); string[] yTypeSubType = y.MediaType.Split('/'); Fx.Assert(xTypeSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); Fx.Assert(yTypeSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); if (string.Equals(xTypeSubType[0], yTypeSubType[0], StringComparison.OrdinalIgnoreCase)) { if (string.Equals(xTypeSubType[1], yTypeSubType[1], StringComparison.OrdinalIgnoreCase)) { // need to check the number of parameters to determine which is more specific bool xHasParam = HasParameters(x); bool yHasParam = HasParameters(y); if (xHasParam && !yHasParam) { return 1; } else if (!xHasParam && yHasParam) { return -1; } } else { if (xTypeSubType[1][0] == '*' && xTypeSubType[1].Length == 1) { return 1; } if (yTypeSubType[1][0] == '*' && yTypeSubType[1].Length == 1) { return -1; } } } else if (xTypeSubType[0][0] == '*' && xTypeSubType[0].Length == 1) { return 1; } else if (yTypeSubType[0][0] == '*' && yTypeSubType[0].Length == 1) { return -1; } decimal qualityDifference = GetQualityFactor(x) - GetQualityFactor(y); if (qualityDifference < 0) { return 1; } else if (qualityDifference > 0) { return -1; } return 0; } decimal GetQualityFactor(ContentType contentType) { decimal result; foreach (string key in contentType.Parameters.Keys) { if (string.Equals("q", key, StringComparison.OrdinalIgnoreCase)) { if (decimal.TryParse(contentType.Parameters[key], numberStyles, CultureInfo.InvariantCulture, out result) && (result <= (decimal)1.0)) { return result; } } } return (decimal)1.0; } bool HasParameters(ContentType contentType) { int number = 0; foreach (string param in contentType.Parameters.Keys) { if (!string.Equals("q", param, StringComparison.OrdinalIgnoreCase)) { number++; } } return (number > 0); } } } } // 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
- TemplateApplicationHelper.cs
- OlePropertyStructs.cs
- PathSegment.cs
- ColumnResult.cs
- SqlStream.cs
- TagPrefixAttribute.cs
- WeakReferenceList.cs
- TemplateInstanceAttribute.cs
- DataServiceRequestArgs.cs
- Blend.cs
- DbConnectionPool.cs
- KernelTypeValidation.cs
- UserMapPath.cs
- StretchValidation.cs
- StringPropertyBuilder.cs
- CssClassPropertyAttribute.cs
- XamlSerializer.cs
- WebBaseEventKeyComparer.cs
- CodeRemoveEventStatement.cs
- ZipIOBlockManager.cs
- StateBag.cs
- SQLStringStorage.cs
- ToolStripContentPanel.cs
- ExpressionEditorAttribute.cs
- CleanUpVirtualizedItemEventArgs.cs
- HMACSHA384.cs
- Section.cs
- BasePropertyDescriptor.cs
- HostProtectionException.cs
- TdsEnums.cs
- ServicesExceptionNotHandledEventArgs.cs
- SplineKeyFrames.cs
- XhtmlBasicLabelAdapter.cs
- WebBrowserPermission.cs
- MasterPage.cs
- PixelFormatConverter.cs
- CodeDomSerializerBase.cs
- XmlArrayAttribute.cs
- EntityKey.cs
- Point.cs
- DtdParser.cs
- EntityWithKeyStrategy.cs
- Terminate.cs
- ProgramNode.cs
- CellLabel.cs
- ManipulationDelta.cs
- TextRenderer.cs
- DodSequenceMerge.cs
- TemplatePropertyEntry.cs
- CallbackHandler.cs
- DataKeyArray.cs
- UserValidatedEventArgs.cs
- OpenFileDialog.cs
- OutputScopeManager.cs
- sapiproxy.cs
- EntityProviderServices.cs
- Socket.cs
- XomlCompilerParameters.cs
- Vector3DAnimationBase.cs
- ReceiveErrorHandling.cs
- ContentDesigner.cs
- ExplicitDiscriminatorMap.cs
- CultureInfo.cs
- AuthenticationServiceManager.cs
- ListViewTableRow.cs
- TextSpanModifier.cs
- RuntimeHelpers.cs
- MultiByteCodec.cs
- RangeValueProviderWrapper.cs
- PointAnimationBase.cs
- RadioButton.cs
- QueryStringHandler.cs
- TextBoxView.cs
- BamlLocalizer.cs
- LocationEnvironment.cs
- SingleAnimationBase.cs
- TransformValueSerializer.cs
- HashCodeCombiner.cs
- SqlVisitor.cs
- MexBindingBindingCollectionElement.cs
- SignatureToken.cs
- ADMembershipProvider.cs
- SqlUdtInfo.cs
- CompensationHandlingFilter.cs
- ValueOfAction.cs
- XmlSchemaNotation.cs
- HtmlInputReset.cs
- PageTrueTypeFont.cs
- TdsParserSessionPool.cs
- FileSecurity.cs
- Pen.cs
- XmlSchemaAnnotation.cs
- SafeProcessHandle.cs
- Point4DValueSerializer.cs
- DataBoundLiteralControl.cs
- PropertyStore.cs
- ClientSession.cs
- TextHidden.cs
- ConstraintEnumerator.cs
- OperationDescription.cs