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
- PropertyDescriptorGridEntry.cs
- UniformGrid.cs
- SmtpMail.cs
- Compress.cs
- FolderLevelBuildProvider.cs
- DescriptionAttribute.cs
- JsonServiceDocumentSerializer.cs
- BoundPropertyEntry.cs
- InvalidOperationException.cs
- TemplateXamlParser.cs
- Simplifier.cs
- BaseServiceProvider.cs
- IntSecurity.cs
- AtomPub10CategoriesDocumentFormatter.cs
- SystemInfo.cs
- CollectionBase.cs
- Table.cs
- GridItemProviderWrapper.cs
- SByteConverter.cs
- OperationSelectorBehavior.cs
- StylusPlugInCollection.cs
- XmlSchemaValidator.cs
- TextServicesLoader.cs
- IssuanceLicense.cs
- FactoryGenerator.cs
- HorizontalAlignConverter.cs
- Int32CAMarshaler.cs
- XsdValidatingReader.cs
- coordinatorfactory.cs
- XamlClipboardData.cs
- DataRowView.cs
- RawKeyboardInputReport.cs
- EntityWithChangeTrackerStrategy.cs
- TextTreeInsertElementUndoUnit.cs
- PropertyReference.cs
- ApplicationFileParser.cs
- EntityClientCacheEntry.cs
- Canvas.cs
- SubpageParagraph.cs
- SqlBooleanMismatchVisitor.cs
- ProcessManager.cs
- SqlNotificationRequest.cs
- RubberbandSelector.cs
- MetadataFile.cs
- ControlParameter.cs
- StringDictionary.cs
- TransformCollection.cs
- DBConnection.cs
- ClientSideQueueItem.cs
- MemoryStream.cs
- ViewSimplifier.cs
- DesignerPainter.cs
- BulletChrome.cs
- SvcMapFileSerializer.cs
- PermissionSetEnumerator.cs
- FastEncoderStatics.cs
- LightweightCodeGenerator.cs
- ObjectDataSourceFilteringEventArgs.cs
- SelectionUIHandler.cs
- BatchParser.cs
- FileEnumerator.cs
- ListViewGroupItemCollection.cs
- ConstraintEnumerator.cs
- CustomErrorsSectionWrapper.cs
- DeviceContext.cs
- FileDataSourceCache.cs
- tabpagecollectioneditor.cs
- OperationContextScope.cs
- _UriTypeConverter.cs
- MessageHeaderT.cs
- DataBindingValueUIHandler.cs
- XPathEmptyIterator.cs
- SetterBase.cs
- AppDomainEvidenceFactory.cs
- DataGridViewCellParsingEventArgs.cs
- StringExpressionSet.cs
- HashAlgorithm.cs
- UrlUtility.cs
- ServicePoint.cs
- WebPageTraceListener.cs
- BigInt.cs
- DockProviderWrapper.cs
- WorkflowMessageEventArgs.cs
- DetailsViewUpdatedEventArgs.cs
- EntityTypeBase.cs
- WebPartCloseVerb.cs
- ViewLoader.cs
- XmlDataDocument.cs
- ScrollChangedEventArgs.cs
- ImplicitInputBrush.cs
- MultiPropertyDescriptorGridEntry.cs
- GridErrorDlg.cs
- StringFormat.cs
- XamlPoint3DCollectionSerializer.cs
- Label.cs
- TypeSystemProvider.cs
- util.cs
- PagerSettings.cs
- SignedXml.cs
- TriState.cs