Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx35 / System.ServiceModel.Web / System / ServiceModel / Web / CachingParameterInspector.cs / 1305376 / CachingParameterInspector.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.Serialization;
using System.Security;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Web;
using System.Web.Caching;
using System.Web.Configuration;
using System.Web.UI;
using System.ServiceModel.Activation;
namespace System.ServiceModel.Web
{
class CachingParameterInspector : IParameterInspector
{
const char seperatorChar = ';';
const char escapeChar = '\\';
const char tableDbSeperatorChar = ':';
const string invalidSqlDependencyString = "Invalid Sql dependency string.";
[Fx.Tag.SecurityNote(Critical = "A config object, which should not be leaked.")]
[SecurityCritical]
OutputCacheProfile cacheProfile;
SqlDependencyInfo[] cacheDependencyInfoArray;
[Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.",
Safe="The config object never leaves the CachingParameterInspector.")]
[SecuritySafeCritical]
public CachingParameterInspector(string cacheProfileName)
{
if (string.IsNullOrEmpty(cacheProfileName))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.CacheProfileNameNullOrEmpty));
}
OutputCacheSettingsSection cacheSettings = AspNetEnvironment.Current.UnsafeGetConfigurationSection("system.web/caching/outputCacheSettings") as OutputCacheSettingsSection;
if (cacheSettings == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileNotConfigured, cacheProfileName)));
}
this.cacheProfile = cacheSettings.OutputCacheProfiles[cacheProfileName];
if (this.cacheProfile == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileNotConfigured, cacheProfileName)));
}
// Validate the cacheProfile
if (this.cacheProfile.Location != OutputCacheLocation.None)
{
// Duration must be set; Duration default value is -1
if (this.cacheProfile.Duration == -1)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileValueMissing, this.cacheProfile.Name, "Duration")));
}
if (this.cacheProfile.VaryByParam == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileValueMissing, this.cacheProfile.Name, "VaryByParam")));
}
}
if (string.Equals(this.cacheProfile.SqlDependency, "CommandNotification", StringComparison.OrdinalIgnoreCase))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.CommandNotificationSqlDependencyNotSupported));
}
if (!string.IsNullOrEmpty(this.cacheProfile.SqlDependency))
{
ParseSqlDependencyString(cacheProfile.SqlDependency);
}
}
[Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.",
Safe = "The config object never leaves the CachingParameterInspector.")]
[SecuritySafeCritical]
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
if (this.cacheProfile != null &&
this.cacheProfile.Enabled &&
OperationContext.Current.IncomingMessage.Version == MessageVersion.None)
{
if (DiagnosticUtility.ShouldTraceWarning && !IsAnonymous())
{
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AddingAuthenticatedResponseToOutputCache, SR2.GetString(SR2.TraceCodeAddingAuthenticatedResponseToOutputCache, operationName));
}
else if (DiagnosticUtility.ShouldTraceInformation)
{
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AddingResponseToOutputCache, SR2.GetString(SR2.TraceCodeAddingResponseToOutputCache, operationName));
}
SetCacheFromCacheProfile();
}
}
public object BeforeCall(string operationName, object[] inputs)
{
return null;
}
bool IsAnonymous()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
return false;
}
else
{
if (OperationContext.Current.ServiceSecurityContext == null)
{
return true;
}
else
{
return OperationContext.Current.ServiceSecurityContext.IsAnonymous;
}
}
}
static SqlDependencyInfo[] ParseSqlDependencyString(string sqlDependencyString)
{
// The code for this method was taken from private code in
// System.Web.SqlCacheDependency.ParseSql7OutputCacheDependency.
// Alter if only absolutely necessary since we want to reproduce the same ASP.NET caching behavior.
List dependencyList = new List();
bool escapeSequenceFlag = false;
int startIndexForDatabaseName = 0;
int startIndexForTableName = -1;
string databaseName = null;
try
{
for (int currentIndex = 0; currentIndex < (sqlDependencyString.Length + 1); currentIndex++)
{
if (escapeSequenceFlag)
{
escapeSequenceFlag = false;
}
else if ((currentIndex != sqlDependencyString.Length) &&
(sqlDependencyString[currentIndex] == escapeChar))
{
escapeSequenceFlag = true;
}
else
{
int subStringLength;
if ((currentIndex == sqlDependencyString.Length) ||
(sqlDependencyString[currentIndex] == seperatorChar))
{
if (databaseName == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
}
subStringLength = currentIndex - startIndexForTableName;
if (subStringLength == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
}
string tableName = sqlDependencyString.Substring(startIndexForTableName, subStringLength);
SqlDependencyInfo info = new SqlDependencyInfo();
info.Database = VerifyAndRemoveEscapeCharacters(databaseName);
info.Table = VerifyAndRemoveEscapeCharacters(tableName);
dependencyList.Add(info);
startIndexForDatabaseName = currentIndex + 1;
databaseName = null;
}
if (currentIndex == sqlDependencyString.Length)
{
break;
}
if (sqlDependencyString[currentIndex] == tableDbSeperatorChar)
{
if (databaseName != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
}
subStringLength = currentIndex - startIndexForDatabaseName;
if (subStringLength == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
}
databaseName = sqlDependencyString.Substring(startIndexForDatabaseName, subStringLength);
startIndexForTableName = currentIndex + 1;
}
}
}
}
catch (ArgumentException)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileSqlDependencyIsInvalid, sqlDependencyString)));
}
if (dependencyList.Count == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileSqlDependencyIsInvalid, sqlDependencyString)));
}
return dependencyList.ToArray();
}
static string VerifyAndRemoveEscapeCharacters(string str)
{
// The code for this method was taken from private code in
// System.Web.SqlCacheDependency.VerifyAndRemoveEscapeCharacters.
// Alter if only absolutely necessary since we want to reproduce the same ASP.NET caching behavior.
bool escapeSequenceFlag = false;
for (int currentIndex = 0; currentIndex < str.Length; currentIndex++)
{
if (escapeSequenceFlag)
{
if (((str[currentIndex] != escapeChar) &&
(str[currentIndex] != tableDbSeperatorChar)) &&
(str[currentIndex] != seperatorChar))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(str);
}
escapeSequenceFlag = false;
}
else if (str[currentIndex] == escapeChar)
{
if ((currentIndex + 1) == str.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(str);
}
escapeSequenceFlag = true;
str = str.Remove(currentIndex, 1);
currentIndex--;
}
}
return str;
}
CacheDependency CreateSingleCacheDependency(string sqlDependency)
{
if (this.cacheDependencyInfoArray == null)
{
this.cacheDependencyInfoArray = CachingParameterInspector.ParseSqlDependencyString(sqlDependency);
}
// cacheDependencyInfoArray will never have length = 0
if (this.cacheDependencyInfoArray.Length == 1)
{
return new SqlCacheDependency(this.cacheDependencyInfoArray[0].Database, this.cacheDependencyInfoArray[0].Table);
}
AggregateCacheDependency cacheDependency = new AggregateCacheDependency();
foreach (SqlDependencyInfo dependencyInfo in this.cacheDependencyInfoArray)
{
cacheDependency.Add(new CacheDependency[] { new SqlCacheDependency(dependencyInfo.Database, dependencyInfo.Table) });
}
return cacheDependency;
}
[Fx.Tag.SecurityNote(Critical = "Uses config object to set properties of the HttpCachePolicy.",
Safe = "The config object itself doesn't leak.")]
[SecuritySafeCritical]
void SetCacheFromCacheProfile()
{
HttpCachePolicy cache = HttpContext.Current.Response.Cache;
if (this.cacheProfile.NoStore)
{
cache.SetNoStore();
}
// Location is not required to be set in the config. The default is Any,
// but if it is not set in the config the value will be -1. So must correct for this.
if ((int)(this.cacheProfile.Location) == -1)
{
cache.SetCacheability(HttpCacheability.Public);
}
else
{
switch (this.cacheProfile.Location)
{
case OutputCacheLocation.Any:
cache.SetCacheability(HttpCacheability.Public);
break;
case OutputCacheLocation.Client:
cache.SetCacheability(HttpCacheability.Private);
break;
case OutputCacheLocation.Downstream:
cache.SetCacheability(HttpCacheability.Public);
cache.SetNoServerCaching();
break;
case OutputCacheLocation.None:
cache.SetCacheability(HttpCacheability.NoCache);
break;
case OutputCacheLocation.Server:
cache.SetCacheability(HttpCacheability.ServerAndNoCache);
break;
case OutputCacheLocation.ServerAndClient:
cache.SetCacheability(HttpCacheability.ServerAndPrivate);
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.CacheProfileLocationNotSupported, this.cacheProfile.Location)));
}
}
if (this.cacheProfile.Location != OutputCacheLocation.None)
{
cache.SetExpires(HttpContext.Current.Timestamp.AddSeconds((double)this.cacheProfile.Duration));
cache.SetMaxAge(new TimeSpan(0, 0, this.cacheProfile.Duration));
cache.SetValidUntilExpires(true);
cache.SetLastModified(HttpContext.Current.Timestamp);
if (this.cacheProfile.Location != OutputCacheLocation.Client)
{
if (!string.IsNullOrEmpty(this.cacheProfile.VaryByContentEncoding))
{
foreach (string contentEncoding in this.cacheProfile.VaryByContentEncoding.Split(seperatorChar))
{
cache.VaryByContentEncodings[contentEncoding.Trim()] = true;
}
}
if (!string.IsNullOrEmpty(this.cacheProfile.VaryByHeader))
{
foreach (string header in this.cacheProfile.VaryByHeader.Split(seperatorChar))
{
cache.VaryByHeaders[header.Trim()] = true;
}
}
if (this.cacheProfile.Location != OutputCacheLocation.Downstream)
{
if (!string.IsNullOrEmpty(this.cacheProfile.VaryByCustom))
{
cache.SetVaryByCustom(this.cacheProfile.VaryByCustom);
}
if (!string.IsNullOrEmpty(this.cacheProfile.VaryByParam))
{
foreach (string parameter in cacheProfile.VaryByParam.Split(seperatorChar))
{
cache.VaryByParams[parameter.Trim()] = true;
}
}
if (!string.IsNullOrEmpty(this.cacheProfile.SqlDependency))
{
CacheDependency cacheDependency = this.CreateSingleCacheDependency(cacheProfile.SqlDependency);
HttpContext.Current.Response.AddCacheDependency(new CacheDependency[] { cacheDependency });
}
}
}
}
}
private struct SqlDependencyInfo
{
public string Database;
public string Table;
}
}
}
// 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
- AssociationEndMember.cs
- XmlChildNodes.cs
- SHA1.cs
- ContainerSelectorBehavior.cs
- SqlDependency.cs
- ObjectQueryProvider.cs
- DescriptionAttribute.cs
- FtpWebResponse.cs
- CommandManager.cs
- NotifyIcon.cs
- WebPartMenu.cs
- EventListener.cs
- FilteredSchemaElementLookUpTable.cs
- SubMenuStyle.cs
- PreProcessInputEventArgs.cs
- OleDbMetaDataFactory.cs
- ActivityPreviewDesigner.cs
- WebPartDescriptionCollection.cs
- BoundConstants.cs
- OleDbInfoMessageEvent.cs
- NotifyCollectionChangedEventArgs.cs
- Message.cs
- ManagementOptions.cs
- UrlMappingsSection.cs
- SafePipeHandle.cs
- SamlSecurityTokenAuthenticator.cs
- Button.cs
- TypeContext.cs
- Rectangle.cs
- ModulesEntry.cs
- EntityDataSourceStatementEditorForm.cs
- XhtmlConformanceSection.cs
- TextTreeInsertElementUndoUnit.cs
- InputScopeNameConverter.cs
- StyleCollection.cs
- ZoneButton.cs
- ColumnResizeAdorner.cs
- DataGridState.cs
- DataServiceHostFactory.cs
- NetTcpBindingCollectionElement.cs
- LocalBuilder.cs
- UnmanagedMemoryStreamWrapper.cs
- TableRow.cs
- XmlSchemaInfo.cs
- FontSourceCollection.cs
- PassportAuthenticationEventArgs.cs
- EndpointAddress.cs
- UIElementParagraph.cs
- HtmlTitle.cs
- WebPartDescription.cs
- XamlToRtfParser.cs
- BlurBitmapEffect.cs
- SafeArrayTypeMismatchException.cs
- PackagePartCollection.cs
- ToolStripDropDownMenu.cs
- Pen.cs
- MdiWindowListItemConverter.cs
- NotificationContext.cs
- CompositeTypefaceMetrics.cs
- DataRelationCollection.cs
- ProxyGenerationError.cs
- FontFaceLayoutInfo.cs
- InfoCardKeyedHashAlgorithm.cs
- HandleCollector.cs
- XmlSchemaComplexContentRestriction.cs
- XmlILCommand.cs
- DataSourceComponent.cs
- HtmlImage.cs
- AddInAttribute.cs
- PathTooLongException.cs
- OleDbException.cs
- InputLangChangeRequestEvent.cs
- ConstructorArgumentAttribute.cs
- TCEAdapterGenerator.cs
- ACL.cs
- NetworkStream.cs
- DesignerAdapterUtil.cs
- XmlUtilWriter.cs
- DecimalFormatter.cs
- SecurityElement.cs
- XmlSchemaObject.cs
- TemplateBindingExtensionConverter.cs
- HttpModuleAction.cs
- DirectionalLight.cs
- LineVisual.cs
- Permission.cs
- SizeChangedEventArgs.cs
- EntityDataSourceSelectedEventArgs.cs
- NumericUpDown.cs
- TracedNativeMethods.cs
- SynchronizingStream.cs
- DateTime.cs
- EntityConnectionStringBuilder.cs
- CompositeDataBoundControl.cs
- UpDownEvent.cs
- Journaling.cs
- TerminateSequenceResponse.cs
- AttributeCollection.cs
- SqlDataSourceCommandParser.cs
- TlsnegoTokenProvider.cs