Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,14 @@
namespace System.Web.Routing {
// Represents a URL generated from a ParsedRoute
internal class BoundUrl {
public string Url {
get;
set;
}
public RouteValueDictionary Values {
get;
set;
}
}
}

View File

@@ -0,0 +1,43 @@
namespace System.Web.Routing {
using System.Collections.Generic;
using System.Linq;
// Represents a segment of a URL that is not a separator. It contains subsegments such as literals and parameters.
internal sealed class ContentPathSegment : PathSegment {
public ContentPathSegment(IList<PathSubsegment> subsegments) {
Subsegments = subsegments;
}
public bool IsCatchAll {
get {
//
return Subsegments.Any<PathSubsegment>(seg => (seg is ParameterSubsegment) && (((ParameterSubsegment)seg).IsCatchAll));
}
}
public IList<PathSubsegment> Subsegments {
get;
private set;
}
#if ROUTE_DEBUGGING
public override string LiteralText {
get {
List<string> s = new List<string>();
foreach (PathSubsegment subsegment in Subsegments) {
s.Add(subsegment.LiteralText);
}
return String.Join(String.Empty, s.ToArray());
}
}
public override string ToString() {
List<string> s = new List<string>();
foreach (PathSubsegment subsegment in Subsegments) {
s.Add(subsegment.ToString());
}
return "[ " + String.Join(", ", s.ToArray()) + " ]";
}
#endif
}
}

View File

@@ -0,0 +1,83 @@
namespace System.Web.Routing {
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class HttpMethodConstraint : IRouteConstraint {
public HttpMethodConstraint(params string[] allowedMethods) {
if (allowedMethods == null) {
throw new ArgumentNullException("allowedMethods");
}
AllowedMethods = allowedMethods.ToList().AsReadOnly();
}
public ICollection<string> AllowedMethods {
get;
private set;
}
protected virtual bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
if (route == null) {
throw new ArgumentNullException("route");
}
if (parameterName == null) {
throw new ArgumentNullException("parameterName");
}
if (values == null) {
throw new ArgumentNullException("values");
}
switch (routeDirection) {
case RouteDirection.IncomingRequest:
return AllowedMethods.Any(method => String.Equals(method, httpContext.Request.HttpMethod,
StringComparison.OrdinalIgnoreCase));
case RouteDirection.UrlGeneration:
// We need to see if the user specified the HTTP method explicitly. Consider these two routes:
//
// a) Route: Url = "/{foo}", Constraints = { httpMethod = new HttpMethodConstraint("GET") }
// b) Route: Url = "/{foo}", Constraints = { httpMethod = new HttpMethodConstraint("POST") }
//
// A user might know ahead of time that a URL he is generating might be used with a particular HTTP
// method. If a URL will be used for an HTTP POST but we match on (a) while generating the URL, then
// the HTTP GET-specific route will be used for URL generation, which might have undesired behavior.
// To prevent this, a user might call RouteCollection.GetVirtualPath(..., { httpMethod = "POST" }) to
// signal that he is generating a URL that will be used for an HTTP POST, so he wants the URL
// generation to be performed by the (b) route instead of the (a) route, consistent with what would
// happen on incoming requests.
object parameterValue;
if (!values.TryGetValue(parameterName, out parameterValue)) {
return true;
}
string parameterValueString = parameterValue as string;
if (parameterValueString == null) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
SR.GetString(SR.HttpMethodConstraint_ParameterValueMustBeString), parameterName, route.Url));
}
return AllowedMethods.Any(method => String.Equals(method, parameterValueString,
StringComparison.OrdinalIgnoreCase));
default:
return true;
}
}
#region IRouteConstraint Members
bool IRouteConstraint.Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
return Match(httpContext, route, parameterName, values, routeDirection);
}
#endregion
}
}

View File

@@ -0,0 +1,9 @@
namespace System.Web.Routing {
using System.Web;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public interface IRouteConstraint {
bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
}
}

View File

@@ -0,0 +1,8 @@
namespace System.Web.Routing {
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public interface IRouteHandler {
IHttpHandler GetHttpHandler(RequestContext requestContext);
}
}

View File

@@ -0,0 +1,26 @@
namespace System.Web.Routing {
// Represents a literal subsegment of a ContentPathSegment
internal sealed class LiteralSubsegment : PathSubsegment {
public LiteralSubsegment(string literal) {
Literal = literal;
}
public string Literal {
get;
private set;
}
#if ROUTE_DEBUGGING
public override string LiteralText {
get {
return Literal;
}
}
public override string ToString() {
return "\"" + Literal + "\"";
}
#endif
}
}

View File

@@ -0,0 +1,114 @@
//------------------------------------------------------------------------------
// <copyright file="WebFormRouteHandler.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Routing {
using System;
using System.Web.UI;
using System.Web.Compilation;
using System.Web.Security;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
public class PageRouteHandler : IRouteHandler {
public PageRouteHandler(string virtualPath)
: this(virtualPath, true) {
}
public PageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess) {
if (string.IsNullOrEmpty(virtualPath) || !virtualPath.StartsWith("~/", StringComparison.OrdinalIgnoreCase)) {
throw new ArgumentException(SR.GetString(SR.PageRouteHandler_InvalidVirtualPath), "virtualPath");
}
this.VirtualPath = virtualPath;
this.CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
_useRouteVirtualPath = VirtualPath.Contains("{");
}
/// <summary>
/// This is the full virtual path (using tilde syntax) to the WebForm page.
/// </summary>
/// <remarks>
/// Needs to be thread safe so this is only settable via ctor.
/// </remarks>
public string VirtualPath { get; private set; }
/// <summary>
/// Because we're not actually rewriting the URL, ASP.NET's URL Auth will apply
/// to the incoming request URL and not the URL of the physical WebForm page.
/// Setting this to true (default) will apply URL access rules against the
/// physical file.
/// </summary>
/// <value>True by default</value>
public bool CheckPhysicalUrlAccess { get; private set; }
private bool _useRouteVirtualPath;
private Route _routeVirtualPath;
private Route RouteVirtualPath {
get {
if (_routeVirtualPath == null) {
//Trim off ~/
_routeVirtualPath = new Route(VirtualPath.Substring(2), this);
}
return _routeVirtualPath;
}
}
private bool CheckUrlAccess(string virtualPath, RequestContext requestContext) {
IPrincipal user = requestContext.HttpContext.User;
// If there's no authenticated user, use the default identity
if (user == null) {
user = new GenericPrincipal(new GenericIdentity(String.Empty, String.Empty), new string[0]);
}
return CheckUrlAccessWithAssert(virtualPath, requestContext, user);
}
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
private bool CheckUrlAccessWithAssert(string virtualPath, RequestContext requestContext, IPrincipal user) {
return UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath, user, requestContext.HttpContext.Request.HttpMethod);
}
public virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
if (requestContext == null) {
throw new ArgumentNullException("requestContext");
}
string virtualPath = GetSubstitutedVirtualPath(requestContext);
// Virtual Path ----s up with query strings, so we need to strip them off
int qmark = virtualPath.IndexOf('?');
if (qmark != -1) {
virtualPath = virtualPath.Substring(0, qmark);
}
if (this.CheckPhysicalUrlAccess && !CheckUrlAccess(virtualPath, requestContext)) {
return new UrlAuthFailureHandler();
}
Page page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page)) as Page;
return page;
}
/// <summary>
/// Gets the virtual path to the resource after applying substitutions based on route data.
/// </summary>
/// <param name="requestContext"></param>
/// <returns></returns>
public string GetSubstitutedVirtualPath(RequestContext requestContext) {
if (requestContext == null) {
throw new ArgumentNullException("requestContext");
}
if (!_useRouteVirtualPath)
return VirtualPath;
VirtualPathData vpd = RouteVirtualPath.GetVirtualPath(requestContext, requestContext.RouteData.Values);
//
if (vpd == null)
return VirtualPath;
return "~/" + vpd.VirtualPath;
}
}
}

View File

@@ -0,0 +1,37 @@
namespace System.Web.Routing {
// Represents a parameter subsegment of a ContentPathSegment
internal sealed class ParameterSubsegment : PathSubsegment {
public ParameterSubsegment(string parameterName) {
if (parameterName.StartsWith("*", StringComparison.Ordinal)) {
ParameterName = parameterName.Substring(1);
IsCatchAll = true;
}
else {
ParameterName = parameterName;
}
}
public bool IsCatchAll {
get;
private set;
}
public string ParameterName {
get;
private set;
}
#if ROUTE_DEBUGGING
public override string LiteralText {
get {
return "{" + (IsCatchAll ? "*" : String.Empty) + ParameterName + "}";
}
}
public override string ToString() {
return "{" + (IsCatchAll ? "*" : String.Empty) + ParameterName + "}";
}
#endif
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
namespace System.Web.Routing {
// Represents a segment of a URL such as a separator or content
internal abstract class PathSegment {
#if ROUTE_DEBUGGING
public abstract string LiteralText {
get;
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
namespace System.Web.Routing {
// Represents a subsegment of a ContentPathSegment such as a parameter or a literal.
internal abstract class PathSubsegment {
#if ROUTE_DEBUGGING
public abstract string LiteralText {
get;
}
#endif
}
}

View File

@@ -0,0 +1,33 @@
namespace System.Web.Routing {
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class RequestContext {
public RequestContext() {
}
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
public RequestContext(HttpContextBase httpContext, RouteData routeData) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
if (routeData == null) {
throw new ArgumentNullException("routeData");
}
HttpContext = httpContext;
RouteData = routeData;
}
public virtual HttpContextBase HttpContext {
get;
set;
}
public virtual RouteData RouteData {
get;
set;
}
}
}

View File

@@ -0,0 +1,186 @@
namespace System.Web.Routing {
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Web;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class Route : RouteBase {
private const string HttpMethodParameterName = "httpMethod";
private string _url;
private ParsedRoute _parsedRoute;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is a URL template with special characters, not just a regular valid URL.")]
public Route(string url, IRouteHandler routeHandler) {
Url = url;
RouteHandler = routeHandler;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is a URL template with special characters, not just a regular valid URL.")]
public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) {
Url = url;
Defaults = defaults;
RouteHandler = routeHandler;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is a URL template with special characters, not just a regular valid URL.")]
public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) {
Url = url;
Defaults = defaults;
Constraints = constraints;
RouteHandler = routeHandler;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is a URL template with special characters, not just a regular valid URL.")]
public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) {
Url = url;
Defaults = defaults;
Constraints = constraints;
DataTokens = dataTokens;
RouteHandler = routeHandler;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
Justification = "This property is settable so people can use object initializers.")]
public RouteValueDictionary Constraints {
get;
set;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
Justification = "This property is settable so people can use object initializers.")]
public RouteValueDictionary DataTokens {
get;
set;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
Justification = "This property is settable so people can use object initializers.")]
public RouteValueDictionary Defaults {
get;
set;
}
public IRouteHandler RouteHandler {
get;
set;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings",
Justification = "This is a URL template with special characters, not just a regular valid URL.")]
public string Url {
get {
return _url ?? String.Empty;
}
set {
// The parser will throw for invalid routes. We don't have to worry
// about _parsedRoute getting out of [....] with _url since the latter
// won't get set unless we can parse the route.
_parsedRoute = RouteParser.Parse(value);
// If we passed the parsing stage, save the original URL value
_url = value;
}
}
public override RouteData GetRouteData(HttpContextBase httpContext) {
// Parse incoming URL (we trim off the first two chars since they're always "~/")
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults);
if (values == null) {
// If we got back a null value set, that means the URL did not match
return null;
}
RouteData routeData = new RouteData(this, RouteHandler);
// Validate the values
if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) {
return null;
}
// Copy the matched values
foreach (var value in values) {
routeData.Values.Add(value.Key, value.Value);
}
// Copy the DataTokens from the Route to the RouteData
if (DataTokens != null) {
foreach (var prop in DataTokens) {
routeData.DataTokens[prop.Key] = prop.Value;
}
}
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
// Try to generate a URL that represents the values passed in based on current
// values from the RouteData and new values using the specified Route.
BoundUrl result = _parsedRoute.Bind(requestContext.RouteData.Values, values, Defaults, Constraints);
if (result == null) {
return null;
}
// Verify that the route matches the validation rules
if (!ProcessConstraints(requestContext.HttpContext, result.Values, RouteDirection.UrlGeneration)) {
return null;
}
VirtualPathData vpd = new VirtualPathData(this, result.Url);
// Add the DataTokens from the Route to the VirtualPathData
if (DataTokens != null) {
foreach (var prop in DataTokens) {
vpd.DataTokens[prop.Key] = prop.Value;
}
}
return vpd;
}
protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
IRouteConstraint customConstraint = constraint as IRouteConstraint;
if (customConstraint != null) {
return customConstraint.Match(httpContext, this, parameterName, values, routeDirection);
}
// If there was no custom constraint, then treat the constraint as a string which represents a Regex.
string constraintsRule = constraint as string;
if (constraintsRule == null) {
throw new InvalidOperationException(String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_ValidationMustBeStringOrCustomConstraint),
parameterName,
Url));
}
object parameterValue;
values.TryGetValue(parameterName, out parameterValue);
string parameterValueString = Convert.ToString(parameterValue, CultureInfo.InvariantCulture);
string constraintsRegEx = "^(" + constraintsRule + ")$";
return Regex.IsMatch(parameterValueString, constraintsRegEx,
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
private bool ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection) {
if (Constraints != null) {
foreach (var constraintsItem in Constraints) {
if (!ProcessConstraint(httpContext, constraintsItem.Value, constraintsItem.Key, values, routeDirection)) {
return false;
}
}
}
return true;
}
}
}

View File

@@ -0,0 +1,21 @@
namespace System.Web.Routing {
using System.Collections.Generic;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public abstract class RouteBase {
public abstract RouteData GetRouteData(HttpContextBase httpContext);
public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
// Default needs to be true to avoid breaking change
private bool _routeExistingFiles = true;
public bool RouteExistingFiles {
get {
return _routeExistingFiles;
}
set {
_routeExistingFiles = value;
}
}
}
}

View File

@@ -0,0 +1,405 @@
namespace System.Web.Routing {
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Web.Hosting;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class RouteCollection : Collection<RouteBase> {
private Dictionary<string, RouteBase> _namedMap = new Dictionary<string, RouteBase>(StringComparer.OrdinalIgnoreCase);
private VirtualPathProvider _vpp;
private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
public RouteCollection() {
}
public RouteCollection(VirtualPathProvider virtualPathProvider) {
VPP = virtualPathProvider;
}
public bool AppendTrailingSlash {
get;
set;
}
public bool LowercaseUrls {
get;
set;
}
public bool RouteExistingFiles {
get;
set;
}
private VirtualPathProvider VPP {
get {
if (_vpp == null) {
return HostingEnvironment.VirtualPathProvider;
}
return _vpp;
}
set {
_vpp = value;
}
}
public RouteBase this[string name] {
get {
if (String.IsNullOrEmpty(name)) {
return null;
}
RouteBase route;
if (_namedMap.TryGetValue(name, out route)) {
return route;
}
return null;
}
}
public void Add(string name, RouteBase item) {
if (item == null) {
throw new ArgumentNullException("item");
}
if (!String.IsNullOrEmpty(name)) {
if (_namedMap.ContainsKey(name)) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.RouteCollection_DuplicateName),
name),
"name");
}
}
Add(item);
if (!String.IsNullOrEmpty(name)) {
_namedMap[name] = item;
}
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Warning was suppressed for consistency with existing similar routing API")]
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile) {
return MapPageRoute(routeName, routeUrl, physicalFile, true /* checkPhysicalUrlAccess */, null, null, null);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Warning was suppressed for consistency with existing similar routing API")]
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess) {
return MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, null, null, null);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Warning was suppressed for consistency with existing similar routing API")]
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults) {
return MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, null, null);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Warning was suppressed for consistency with existing similar routing API")]
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints) {
return MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, constraints, null);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Warning was suppressed for consistency with existing similar routing API")]
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens) {
if (routeUrl == null) {
throw new ArgumentNullException("routeUrl");
}
Route route = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess));
Add(routeName, route);
return route;
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
protected override void ClearItems() {
_namedMap.Clear();
base.ClearItems();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Not worth a breaking change.")]
public IDisposable GetReadLock() {
_rwLock.EnterReadLock();
return new ReadLockDisposable(_rwLock);
}
private RequestContext GetRequestContext(RequestContext requestContext) {
if (requestContext != null) {
return requestContext;
}
HttpContext httpContext = HttpContext.Current;
if (httpContext == null) {
throw new InvalidOperationException(SR.GetString(SR.RouteCollection_RequiresContext));
}
return new RequestContext(new HttpContextWrapper(httpContext), new RouteData());
}
// Returns true if this is a request to an existing file
private bool IsRouteToExistingFile(HttpContextBase httpContext) {
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
return ((requestPath != "~/") &&
(VPP != null) &&
(VPP.FileExists(requestPath) ||
VPP.DirectoryExists(requestPath)));
}
public RouteData GetRouteData(HttpContextBase httpContext) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
if (httpContext.Request == null) {
throw new ArgumentException(SR.GetString(SR.RouteTable_ContextMissingRequest), "httpContext");
}
// Optimize performance when the route collection is empty. The main improvement is that we avoid taking
// a read lock when the collection is empty. Without this check, the UrlRoutingModule causes a 25%-50%
// regression in HelloWorld RPS due to lock contention. The UrlRoutingModule is now in the root web.config,
// so we need to ensure the module is performant, especially when you are not using routing.
// This check does introduce a slight bug, in that if a writer clears the collection as part of a write
// transaction, a reader may see the collection when it's empty, which the read lock is supposed to prevent.
// We will investigate a better fix in Dev10 Beta2. The Beta1 bug is Dev10 652986.
if (Count == 0) {
return null;
}
bool isRouteToExistingFile = false;
bool doneRouteCheck = false; // We only want to do the route check once
if (!RouteExistingFiles) {
isRouteToExistingFile = IsRouteToExistingFile(httpContext);
doneRouteCheck = true;
if (isRouteToExistingFile) {
// If we're not routing existing files and the file exists, we stop processing routes
return null;
}
}
// Go through all the configured routes and find the first one that returns a match
using (GetReadLock()) {
foreach (RouteBase route in this) {
RouteData routeData = route.GetRouteData(httpContext);
if (routeData != null) {
// If we're not routing existing files on this route and the file exists, we also stop processing routes
if (!route.RouteExistingFiles) {
if (!doneRouteCheck) {
isRouteToExistingFile = IsRouteToExistingFile(httpContext);
doneRouteCheck = true;
}
if (isRouteToExistingFile) {
return null;
}
}
return routeData;
}
}
}
return null;
}
[SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.EndsWith(System.String)", Justification = @"okay")]
private string NormalizeVirtualPath(RequestContext requestContext, string virtualPath) {
string url = System.Web.UI.Util.GetUrlWithApplicationPath(requestContext.HttpContext, virtualPath);
if (LowercaseUrls || AppendTrailingSlash) {
int iqs = url.IndexOfAny(new char[] { '?', '#' });
string urlWithoutQs;
string qs;
if (iqs >= 0) {
urlWithoutQs = url.Substring(0, iqs);
qs = url.Substring(iqs);
}
else {
urlWithoutQs = url;
qs = "";
}
// Don't lowercase the query string
if (LowercaseUrls) {
urlWithoutQs = urlWithoutQs.ToLowerInvariant();
}
if (AppendTrailingSlash && !urlWithoutQs.EndsWith("/")) {
urlWithoutQs += "/";
}
url = urlWithoutQs + qs;
}
return url;
}
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
requestContext = GetRequestContext(requestContext);
// Go through all the configured routes and find the first one that returns a match
using (GetReadLock()) {
foreach (RouteBase route in this) {
VirtualPathData vpd = route.GetVirtualPath(requestContext, values);
if (vpd != null) {
vpd.VirtualPath = NormalizeVirtualPath(requestContext, vpd.VirtualPath);
return vpd;
}
}
}
return null;
}
public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values) {
requestContext = GetRequestContext(requestContext);
if (!String.IsNullOrEmpty(name)) {
RouteBase namedRoute;
bool routeFound;
using (GetReadLock()) {
routeFound = _namedMap.TryGetValue(name, out namedRoute);
}
if (routeFound) {
VirtualPathData vpd = namedRoute.GetVirtualPath(requestContext, values);
if (vpd != null) {
vpd.VirtualPath = NormalizeVirtualPath(requestContext, vpd.VirtualPath);
return vpd;
}
return null;
}
else {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.RouteCollection_NameNotFound),
name),
"name");
}
}
else {
return GetVirtualPath(requestContext, values);
}
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Not worth a breaking change.")]
public IDisposable GetWriteLock() {
_rwLock.EnterWriteLock();
return new WriteLockDisposable(_rwLock);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is not a regular URL as it may contain special routing characters.")]
public void Ignore(string url) {
Ignore(url, null /* constraints */);
}
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "This is not a regular URL as it may contain special routing characters.")]
public void Ignore(string url, object constraints) {
if (url == null) {
throw new ArgumentNullException("url");
}
IgnoreRouteInternal route = new IgnoreRouteInternal(url) {
Constraints = new RouteValueDictionary(constraints)
};
Add(route);
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
protected override void InsertItem(int index, RouteBase item) {
if (item == null) {
throw new ArgumentNullException("item");
}
if (Contains(item)) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
SR.GetString(SR.RouteCollection_DuplicateEntry)),
"item");
}
base.InsertItem(index, item);
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
protected override void RemoveItem(int index) {
RemoveRouteName(index);
base.RemoveItem(index);
}
private void RemoveRouteName(int index) {
// Search for the specified route and clear out its name if we have one
RouteBase route = this[index];
foreach (KeyValuePair<string, RouteBase> namedRoute in _namedMap) {
if (namedRoute.Value == route) {
_namedMap.Remove(namedRoute.Key);
break;
}
}
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
protected override void SetItem(int index, RouteBase item) {
if (item == null) {
throw new ArgumentNullException("item");
}
if (Contains(item)) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
SR.GetString(SR.RouteCollection_DuplicateEntry)),
"item");
}
RemoveRouteName(index);
base.SetItem(index, item);
}
private class ReadLockDisposable : IDisposable {
private ReaderWriterLockSlim _rwLock;
public ReadLockDisposable(ReaderWriterLockSlim rwLock) {
_rwLock = rwLock;
}
[SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
Justification = "Type does not have a finalizer.")]
void IDisposable.Dispose() {
_rwLock.ExitReadLock();
}
}
private class WriteLockDisposable : IDisposable {
private ReaderWriterLockSlim _rwLock;
public WriteLockDisposable(ReaderWriterLockSlim rwLock) {
_rwLock = rwLock;
}
[SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
Justification = "Type does not have a finalizer.")]
void IDisposable.Dispose() {
_rwLock.ExitWriteLock();
}
}
private sealed class IgnoreRouteInternal : Route {
public IgnoreRouteInternal(string url)
: base(url, new StopRoutingHandler()) {
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues) {
// Never match during route generation. This avoids the scenario where an IgnoreRoute with
// fairly relaxed constraints ends up eagerly matching all generated URLs.
return null;
}
}
}
}

View File

@@ -0,0 +1,62 @@
namespace System.Web.Routing {
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class RouteData {
private IRouteHandler _routeHandler;
private RouteValueDictionary _values = new RouteValueDictionary();
private RouteValueDictionary _dataTokens = new RouteValueDictionary();
public RouteData() {
}
public RouteData(RouteBase route, IRouteHandler routeHandler) {
Route = route;
RouteHandler = routeHandler;
}
public RouteValueDictionary DataTokens {
get {
return _dataTokens;
}
}
public RouteBase Route {
get;
set;
}
public IRouteHandler RouteHandler {
get {
return _routeHandler;
}
set {
_routeHandler = value;
}
}
public RouteValueDictionary Values {
get {
return _values;
}
}
public string GetRequiredString(string valueName) {
object value;
if (Values.TryGetValue(valueName, out value)) {
string valueString = value as string;
if (!String.IsNullOrEmpty(valueString)) {
return valueString;
}
}
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.RouteData_RequiredValue),
valueName));
}
}
}

View File

@@ -0,0 +1,9 @@
namespace System.Web.Routing {
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public enum RouteDirection {
IncomingRequest,
UrlGeneration
}
}

View File

@@ -0,0 +1,339 @@
namespace System.Web.Routing {
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
internal static class RouteParser {
private static string GetLiteral(string segmentLiteral) {
// Scan for errant single { and } and convert double {{ to { and double }} to }
// First we eliminate all escaped braces and then check if any other braces are remaining
string newLiteral = segmentLiteral.Replace("{{", "").Replace("}}", "");
if (newLiteral.Contains("{") || newLiteral.Contains("}")) {
return null;
}
// If it's a valid format, we unescape the braces
return segmentLiteral.Replace("{{", "{").Replace("}}", "}");
}
private static int IndexOfFirstOpenParameter(string segment, int startIndex) {
// Find the first unescaped open brace
while (true) {
startIndex = segment.IndexOf('{', startIndex);
if (startIndex == -1) {
// If there are no more open braces, stop
return -1;
}
if ((startIndex + 1 == segment.Length) ||
((startIndex + 1 < segment.Length) && (segment[startIndex + 1] != '{'))) {
// If we found an open brace that is followed by a non-open brace, it's
// a parameter delimiter.
// It's also a delimiter if the open brace is the last character - though
// it ends up being being called out as invalid later on.
return startIndex;
}
// Increment by two since we want to skip both the open brace that
// we're on as well as the subsequent character since we know for
// sure that it is part of an escape sequence.
startIndex += 2;
}
}
internal static bool IsSeparator(string s) {
return String.Equals(s, "/", StringComparison.Ordinal);
}
private static bool IsValidParameterName(string parameterName) {
if (parameterName.Length == 0) {
return false;
}
for (int i = 0; i < parameterName.Length; i++) {
char c = parameterName[i];
if (c == '/' || c == '{' || c == '}') {
return false;
}
}
return true;
}
internal static bool IsInvalidRouteUrl(string routeUrl) {
return (routeUrl.StartsWith("~", StringComparison.Ordinal) ||
routeUrl.StartsWith("/", StringComparison.Ordinal) ||
(routeUrl.IndexOf('?') != -1));
}
public static ParsedRoute Parse(string routeUrl) {
if (routeUrl == null) {
routeUrl = String.Empty;
}
if (IsInvalidRouteUrl(routeUrl)) {
throw new ArgumentException(SR.GetString(SR.Route_InvalidRouteUrl), "routeUrl");
}
IList<string> urlParts = SplitUrlToPathSegmentStrings(routeUrl);
Exception ex = ValidateUrlParts(urlParts);
if (ex != null) {
throw ex;
}
IList<PathSegment> pathSegments = SplitUrlToPathSegments(urlParts);
Debug.Assert(urlParts.Count == pathSegments.Count, "The number of string segments should be the same as the number of path segments");
return new ParsedRoute(pathSegments);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly",
Justification = "The exceptions are just constructed here, but they are thrown from a method that does have those parameter names.")]
private static IList<PathSubsegment> ParseUrlSegment(string segment, out Exception exception) {
int startIndex = 0;
List<PathSubsegment> pathSubsegments = new List<PathSubsegment>();
while (startIndex < segment.Length) {
int nextParameterStart = IndexOfFirstOpenParameter(segment, startIndex);
if (nextParameterStart == -1) {
// If there are no more parameters in the segment, capture the remainder as a literal and stop
string lastLiteralPart = GetLiteral(segment.Substring(startIndex));
if (lastLiteralPart == null) {
exception = new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_MismatchedParameter),
segment
),
"routeUrl");
return null;
}
if (lastLiteralPart.Length > 0) {
pathSubsegments.Add(new LiteralSubsegment(lastLiteralPart));
}
break;
}
int nextParameterEnd = segment.IndexOf('}', nextParameterStart + 1);
if (nextParameterEnd == -1) {
exception = new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_MismatchedParameter),
segment
),
"routeUrl");
return null;
}
string literalPart = GetLiteral(segment.Substring(startIndex, nextParameterStart - startIndex));
if (literalPart == null) {
exception = new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_MismatchedParameter),
segment
),
"routeUrl");
return null;
}
if (literalPart.Length > 0) {
pathSubsegments.Add(new LiteralSubsegment(literalPart));
}
string parameterName = segment.Substring(nextParameterStart + 1, nextParameterEnd - nextParameterStart - 1);
pathSubsegments.Add(new ParameterSubsegment(parameterName));
startIndex = nextParameterEnd + 1;
}
exception = null;
return pathSubsegments;
}
private static IList<PathSegment> SplitUrlToPathSegments(IList<string> urlParts) {
List<PathSegment> pathSegments = new List<PathSegment>();
foreach (string pathSegment in urlParts) {
bool isCurrentPartSeparator = IsSeparator(pathSegment);
if (isCurrentPartSeparator) {
pathSegments.Add(new SeparatorPathSegment());
}
else {
Exception exception;
IList<PathSubsegment> subsegments = ParseUrlSegment(pathSegment, out exception);
Debug.Assert(exception == null, "This only gets called after the path has been validated, so there should never be an exception here");
pathSegments.Add(new ContentPathSegment(subsegments));
}
}
return pathSegments;
}
internal static IList<string> SplitUrlToPathSegmentStrings(string url) {
List<string> parts = new List<string>();
if (String.IsNullOrEmpty(url)) {
return parts;
}
int currentIndex = 0;
// Split the incoming URL into individual parts
while (currentIndex < url.Length) {
int indexOfNextSeparator = url.IndexOf('/', currentIndex);
if (indexOfNextSeparator == -1) {
// If there are no more separators, the rest of the string is the last part
string finalPart = url.Substring(currentIndex);
if (finalPart.Length > 0) {
parts.Add(finalPart);
}
break;
}
string nextPart = url.Substring(currentIndex, indexOfNextSeparator - currentIndex);
if (nextPart.Length > 0) {
parts.Add(nextPart);
}
Debug.Assert(url[indexOfNextSeparator] == '/', "The separator char itself should always be a '/'.");
parts.Add("/");
currentIndex = indexOfNextSeparator + 1;
}
return parts;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly",
Justification = "The exceptions are just constructed here, but they are thrown from a method that does have those parameter names.")]
private static Exception ValidateUrlParts(IList<string> pathSegments) {
Debug.Assert(pathSegments != null, "The value should always come from SplitUrl(), and that function should never return null.");
HashSet<string> usedParameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
bool? isPreviousPartSeparator = null;
bool foundCatchAllParameter = false;
foreach (string pathSegment in pathSegments) {
if (foundCatchAllParameter) {
// If we ever start an iteration of the loop and we've already found a
// catchall parameter then we have an invalid URL format.
return new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
SR.GetString(SR.Route_CatchAllMustBeLast)
),
"routeUrl");
}
bool isCurrentPartSeparator;
if (isPreviousPartSeparator == null) {
// Prime the loop with the first value
isPreviousPartSeparator = IsSeparator(pathSegment);
isCurrentPartSeparator = isPreviousPartSeparator.Value;
}
else {
isCurrentPartSeparator = IsSeparator(pathSegment);
// If both the previous part and the current part are separators, it's invalid
if (isCurrentPartSeparator && isPreviousPartSeparator.Value) {
return new ArgumentException(SR.GetString(SR.Route_CannotHaveConsecutiveSeparators), "routeUrl");
}
Debug.Assert(isCurrentPartSeparator != isPreviousPartSeparator.Value, "This assert should only happen if both the current and previous parts are non-separators. This should never happen because consecutive non-separators are always parsed as a single part.");
isPreviousPartSeparator = isCurrentPartSeparator;
}
// If it's not a separator, parse the segment for parameters and validate it
if (!isCurrentPartSeparator) {
Exception exception;
IList<PathSubsegment> subsegments = ParseUrlSegment(pathSegment, out exception);
if (exception != null) {
return exception;
}
exception = ValidateUrlSegment(subsegments, usedParameterNames, pathSegment);
if (exception != null) {
return exception;
}
foundCatchAllParameter = subsegments.Any<PathSubsegment>(seg => (seg is ParameterSubsegment) && (((ParameterSubsegment)seg).IsCatchAll));
}
}
return null;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly",
Justification = "The exceptions are just constructed here, but they are thrown from a method that does have those parameter names.")]
private static Exception ValidateUrlSegment(IList<PathSubsegment> pathSubsegments, HashSet<string> usedParameterNames, string pathSegment) {
bool segmentContainsCatchAll = false;
Type previousSegmentType = null;
foreach (PathSubsegment subsegment in pathSubsegments) {
if (previousSegmentType != null) {
if (previousSegmentType == subsegment.GetType()) {
return new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
SR.GetString(SR.Route_CannotHaveConsecutiveParameters)
),
"routeUrl");
}
}
previousSegmentType = subsegment.GetType();
LiteralSubsegment literalSubsegment = subsegment as LiteralSubsegment;
if (literalSubsegment != null) {
// Nothing to validate for literals - everything is valid
}
else {
ParameterSubsegment parameterSubsegment = subsegment as ParameterSubsegment;
if (parameterSubsegment != null) {
string parameterName = parameterSubsegment.ParameterName;
if (parameterSubsegment.IsCatchAll) {
segmentContainsCatchAll = true;
}
// Check for valid characters in the parameter name
if (!IsValidParameterName(parameterName)) {
return new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_InvalidParameterName),
parameterName
),
"routeUrl");
}
if (usedParameterNames.Contains(parameterName)) {
return new ArgumentException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.Route_RepeatedParameter),
parameterName
),
"routeUrl");
}
else {
usedParameterNames.Add(parameterName);
}
}
else {
Debug.Fail("Invalid path subsegment type");
}
}
}
if (segmentContainsCatchAll && (pathSubsegments.Count != 1)) {
return new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
SR.GetString(SR.Route_CannotHaveCatchAllInMultiSegment)
),
"routeUrl");
}
return null;
}
}
}

View File

@@ -0,0 +1,16 @@
namespace System.Web.Routing {
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors",
Justification = "There is no explicit public constructor defined, and we don't want to add a private one.")]
public class RouteTable {
private static RouteCollection _instance = new RouteCollection();
public static RouteCollection Routes {
get {
return _instance;
}
}
}
}

View File

@@ -0,0 +1,158 @@
namespace System.Web.Routing {
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public class RouteValueDictionary : IDictionary<string, object> {
private Dictionary<string, object> _dictionary;
public RouteValueDictionary() {
_dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
}
public RouteValueDictionary(object values) {
_dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
AddValues(values);
}
public RouteValueDictionary(IDictionary<string, object> dictionary) {
_dictionary = new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public int Count {
get {
return _dictionary.Count;
}
}
public Dictionary<string, object>.KeyCollection Keys {
get {
return _dictionary.Keys;
}
}
public Dictionary<string, object>.ValueCollection Values {
get {
return _dictionary.Values;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public object this[string key] {
get {
object value;
TryGetValue(key, out value);
return value;
}
set {
_dictionary[key] = value;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public void Add(string key, object value) {
_dictionary.Add(key, value);
}
private void AddValues(object values) {
if (values != null) {
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(values);
foreach (PropertyDescriptor prop in props) {
object val = prop.GetValue(values);
Add(prop.Name, val);
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public void Clear() {
_dictionary.Clear();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public bool ContainsKey(string key) {
return _dictionary.ContainsKey(key);
}
public bool ContainsValue(object value) {
return _dictionary.ContainsValue(value);
}
public Dictionary<string, object>.Enumerator GetEnumerator() {
return _dictionary.GetEnumerator();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public bool Remove(string key) {
return _dictionary.Remove(key);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public bool TryGetValue(string key, out object value) {
return _dictionary.TryGetValue(key, out value);
}
#region IDictionary<string,object> Members
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
ICollection<string> IDictionary<string, object>.Keys {
get {
return _dictionary.Keys;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
ICollection<object> IDictionary<string, object>.Values {
get {
return _dictionary.Values;
}
}
#endregion
#region ICollection<KeyValuePair<string,object>> Members
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) {
((ICollection<KeyValuePair<string, object>>)_dictionary).Add(item);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) {
return ((ICollection<KeyValuePair<string, object>>)_dictionary).Contains(item);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) {
((ICollection<KeyValuePair<string, object>>)_dictionary).CopyTo(array, arrayIndex);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
bool ICollection<KeyValuePair<string, object>>.IsReadOnly {
get {
return ((ICollection<KeyValuePair<string, object>>)_dictionary).IsReadOnly;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) {
return ((ICollection<KeyValuePair<string, object>>)_dictionary).Remove(item);
}
#endregion
#region IEnumerable<KeyValuePair<string,object>> Members
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region IEnumerable Members
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More