URL rewriting extensibility example cannot be downloaded

MS XIE 40 Reputation points
2024-10-22T18:25:29.1133333+00:00

https://learn.microsoft.com/zh-cn/iis/extensions/url-rewrite-module/using-custom-rewrite-providers-with-url-rewrite-module?source=recommendations

我很喜欢这里的FileContainsProvider 从文本文件中读取字符串集这个功能。

这里的URL 重写扩展性示例已经无法下载,能否提供新的下载方式,谢谢!

Internet Information Services
0 comments No comments
{count} votes

Accepted answer
  1. XuDong Peng-MSFT 10,746 Reputation points Microsoft Vendor
    2024-10-23T07:37:49.4+00:00

    您好 @MS XIE,

    正如之前告诉您的一样,目前已经不提供下载这个示例,且后期也没有此计划。 如果您一定要实现此需求,你可以参照此文档 为 URL 重写模块开发自定义重写提供程序 来实现。

    具体的操作步骤如下

    1. 创建一个Class Library类库项目,添加如下的文件。 User's image
    2. 一共有6个.cs文件,一个.resx 文件。具体代码将放到答案的最后。
    3. 文件添加后,进行编译,编译成功后,点击属性进行签名。可以创建新的不需要设置密码。 User's image
    4. 编译成功后到路径下 C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools,找到gacutil.exe 和 gacutil.exe.config 文件,复制我们的新建临时文件夹中。
    5. 找到新建的类库项目的编译后的文件.dll。 User's image
    6. 然后将三个文件复制到对应的服务器或者目标主机中。执行以下的命令。
      
         > .\gacutil.exe /i url-rewrite-extensibility.dll
      
         > iisreset
      
      
      User's image
    7. 然后检查是否可以添加Provider。

    User's image

    类库项目中需要的代码如下:

    1.DbProvider.cs

    
    //
    
    // Copyright © Microsoft Corporation. All Rights Reserved.
    
    // This code released under the terms of the
    
    // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
    
    //
    
    using System;
    
    using System.Collections.Generic;
    
    using System.Data;
    
    using System.Data.SqlClient;
    
    using System.Diagnostics.CodeAnalysis;
    
    using System.Globalization;
    
    using System.Threading;
    
    using Microsoft.Web.Iis.Rewrite;
    
    using Microsoft.Web.Iis.Rewrite.Providers;
    
    public sealed class DbProvider : IRewriteProvider, IProviderDescriptor, IDisposable {
    
        private string connectionString;
    
        private string storedProcedure;
    
        private Timer timer;
    
        private IRewriteContext rewriteContext;
    
        public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext) {
    
            this.rewriteContext = rewriteContext;
    
            if (!settings.TryGetValue(SettingNames.ConnectionString, out this.connectionString) || string.IsNullOrEmpty(this.connectionString)) {
    
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.ProviderSettingExpectedFormat, SettingNames.ConnectionString));
    
            }
    
            if (!settings.TryGetValue(SettingNames.StoredProcedure, out this.storedProcedure) || string.IsNullOrEmpty(this.storedProcedure)) {
    
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.ProviderSettingExpectedFormat, SettingNames.StoredProcedure));
    
            }
    
            // CacheMinutesInterval is an optional parameter.
    
            string minutesString;
    
            if (settings.TryGetValue(SettingNames.CacheMinutesInterval, out minutesString))
    
            {
    
                int minutes = 0;
    
                if (!string.IsNullOrEmpty(minutesString) && int.TryParse(minutesString, out minutes) && minutes > 0)
    
                {
    
                    int period = minutes * 60 * 1000;
    
                    this.timer = new Timer(TimerCallback, null, period, period);
    
                }
    
            }
    
        }
    
        [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
    
        public string Rewrite(string value) {
    
            using (SqlConnection connection = new SqlConnection(this.connectionString)) {
    
                using (SqlCommand command = connection.CreateCommand()) {
    
                    command.Parameters.Add("@Input", SqlDbType.NVarChar).Value = value;
    
                    command.CommandType = CommandType.StoredProcedure;
    
                    command.CommandText = this.storedProcedure;
    
                    connection.Open();
    
                    return (string)command.ExecuteScalar();
    
                }
    
            }
    
        }
    
        public IEnumerable<SettingDescriptor> GetSettings() {
    
            yield return new SettingDescriptor(SettingNames.ConnectionString, SettingNames.ConnectionStringFriendlyName);
    
            yield return new SettingDescriptor(SettingNames.StoredProcedure, SettingNames.StoredProcedureFriendlyName);
    
            yield return new SettingDescriptor(SettingNames.CacheMinutesInterval, SettingNames.CacheMinutesIntervalFriendlyName);
    
        }
    
        private void TimerCallback(object state) {
    
            if (this.rewriteContext != null) {
    
                this.rewriteContext.ClearRewriteCache();
    
            }
    
        }
    
        public void Dispose() {
    
            if (this.timer != null) {
    
                this.timer.Dispose();
    
                this.timer = null;
    
            }
    
            this.rewriteContext = null;
    
            GC.SuppressFinalize(this);
    
        }
    
    }
    
    

    2.FileBaseProvider.cs

    
    //
    
    // Copyright © Microsoft Corporation. All Rights Reserved.
    
    // This code released under the terms of the
    
    // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
    
    //
    
    using System;
    
    using System.Collections.Generic;
    
    using System.Globalization;
    
    using System.IO;
    
    using System.Threading;
    
    using Microsoft.Web.Iis.Rewrite;
    
    using Microsoft.Web.Iis.Rewrite.Providers;
    
    public abstract class FileBaseProvider : IRewriteProvider, IProviderDescriptor, IDisposable {
    
        private FileInfo file;
    
        private bool ignoreCase;
    
        private char separator = '\t';
    
        private bool ready;
    
        private FileSystemWatcher sharedWatcher;
    
        private IRewriteContext rewriteContext;
    
        private ReaderWriterLock fileAccessLock = new ReaderWriterLock();
    
        public FileBaseProvider() {
    
        }
    
        ~FileBaseProvider() {
    
            Dispose(false);
    
        }
    
        protected FileInfo File {
    
            get {
    
                return this.file;
    
            }
    
        }
    
        protected bool IgnoreCase {
    
            get {
    
                return this.ignoreCase;
    
            }
    
        }
    
        protected char Separator {
    
            get {
    
                return this.separator;
    
            }
    
        }
    
        public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext) {
    
            string filePath;
    
            if (!settings.TryGetValue(SettingNames.FilePath, out filePath) || string.IsNullOrEmpty(filePath)) {
    
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.ProviderSettingExpectedFormat, SettingNames.FilePath));
    
            }
    
            // Use FileInfo to verify the file name.
    
            this.file = new FileInfo(filePath);
    
            if (!this.file.Exists) {
    
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.FilePathDoesNotExistFormat, this.file.FullName));
    
            }
    
            string ignoreCase;
    
            // IgnoreCase is an optional parameter.
    
            if (settings.TryGetValue(SettingNames.IgnoreCase, out ignoreCase) &&
    
                !string.IsNullOrEmpty(ignoreCase)) {
    
                if (ignoreCase.Equals("1", StringComparison.Ordinal)) {
    
                    this.ignoreCase = true;
    
                }
    
                else if (!ignoreCase.Equals("0", StringComparison.Ordinal)) {
    
                    this.ignoreCase = bool.Parse(ignoreCase);
    
                }
    
            }
    
            string separator;
    
            if (settings.TryGetValue(SettingNames.CharSeparator, out separator)) {
    
                separator = separator.Trim();
    
                if (separator.Length > 0) {
    
                    this.separator = separator[0];
    
                }
    
            }
    
            this.rewriteContext = rewriteContext;
    
            this.sharedWatcher = FileSystemWatcherPool.Instance.GetWatcher(this.file);
    
            this.sharedWatcher.Changed += OnFileChange;
    
            this.sharedWatcher.Deleted += OnFileDeleted;
    
            this.sharedWatcher.Renamed += OnFileRenamed;
    
            this.sharedWatcher.Created += OnFileCreated;
    
        }
    
        public string Rewrite(string input) {
    
            if (!this.ready) {
    
                this.fileAccessLock.AcquireWriterLock(Timeout.Infinite);
    
                try {
    
                    if (!this.ready) {
    
                        LoadTableFromFile();
    
                        this.sharedWatcher.EnableRaisingEvents = true;
    
                        this.ready = true;
    
                    }
    
                }
    
                finally {
    
                    this.fileAccessLock.ReleaseWriterLock();
    
                }
    
            }
    
            if (string.IsNullOrEmpty(input)) {
    
                return string.Empty;
    
            }
    
            this.fileAccessLock.AcquireReaderLock(Timeout.Infinite);
    
            try {
    
                return this.Map(input);
    
            }
    
            finally {
    
                this.fileAccessLock.ReleaseReaderLock();
    
            }
    
        }
    
        public IEnumerable<SettingDescriptor> GetSettings() {
    
            yield return new SettingDescriptor(SettingNames.FilePath, SettingNames.FilePathFriendlyName);
    
            yield return new SettingDescriptor(SettingNames.IgnoreCase, SettingNames.IgnoreCaseFriendlyName);
    
            foreach (SettingDescriptor value in GetAdditionalSettings()) {
    
                yield return value;
    
            }
    
        }
    
        private void OnFileChange(object sender, FileSystemEventArgs e) {
    
            InvalidateRewriteCache();
    
        }
    
        private void OnFileCreated(object sender, FileSystemEventArgs e) {
    
            InvalidateRewriteCache();
    
        }
    
        private void OnFileRenamed(object sender, RenamedEventArgs e) {
    
            InvalidateRewriteCache();
    
        }
    
        private void OnFileDeleted(object sender, FileSystemEventArgs e) {
    
            InvalidateRewriteCache();
    
        }
    
        private void InvalidateRewriteCache() {
    
            if (this.ready) {
    
                rewriteContext.ClearRewriteCache();
    
                this.ready = false;
    
            }
    
        }
    
        protected abstract void LoadTableFromFile();
    
        protected abstract string Map(string input);
    
        protected abstract IEnumerable<SettingDescriptor> GetAdditionalSettings();
    
        public void Dispose() {
    
            Dispose(true);
    
            GC.SuppressFinalize(this);
    
        }
    
        protected virtual void Dispose(bool disposing) {
    
            if (disposing) {
    
                if (this.sharedWatcher != null) {
    
                    this.sharedWatcher.Changed -= OnFileChange;
    
                    this.sharedWatcher.Deleted -= OnFileDeleted;
    
                    this.sharedWatcher.Renamed -= OnFileRenamed;
    
                    this.sharedWatcher.Created -= OnFileCreated;
    
                    this.sharedWatcher = null;
    
                }
    
            }
    
        }
    
        private sealed class FileSystemWatcherPool {
    
            private Dictionary<string, WeakReference> watchers = new Dictionary<string, WeakReference>(StringComparer.OrdinalIgnoreCase);
    
            private ReaderWriterLock watchersLock = new ReaderWriterLock();
    
            private Timer cleanupTimer;
    
            private const int OneMinute = 60 * 1000;
    
            private static FileSystemWatcherPool sInstance;
    
            private static object sLock = new object();
    
            private FileSystemWatcherPool() {
    
                this.cleanupTimer = new Timer(InvalidateWatcherList, null, OneMinute, OneMinute);
    
            }
    
            public static FileSystemWatcherPool Instance {
    
                get {
    
                    if (sInstance == null) {
    
                        lock (sLock) {
    
                            if (sInstance == null) {
    
                                sInstance = new FileSystemWatcherPool();
    
                            }
    
                        }
    
                    }
    
                    return sInstance;
    
                }
    
            }
    
            public FileSystemWatcher GetWatcher(FileInfo file) {
    
                WeakReference reference;
    
                FileSystemWatcher instance = null;
    
                this.watchersLock.AcquireReaderLock(Timeout.Infinite);
    
                try {
    
                    if (this.watchers.TryGetValue(file.FullName, out reference) && reference.IsAlive) {
    
                        instance = (FileSystemWatcher)reference.Target;
    
                    }
    
                }
    
                finally {
    
                    this.watchersLock.ReleaseReaderLock();
    
                }
    
                if (instance != null) {
    
                    return instance;
    
                }
    
                // Create a new one and add it to the pool.
    
                instance = new FileSystemWatcher();
    
                instance.Path = file.DirectoryName;
    
                instance.Filter = file.Name;
    
                instance.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
    
                this.watchersLock.AcquireWriterLock(Timeout.Infinite);
    
                try {
    
                    this.watchers[file.FullName] = new WeakReference(instance);
    
                }
    
                finally {
    
                    this.watchersLock.ReleaseWriterLock();
    
                }
    
                return instance;
    
            }
    
            private void InvalidateWatcherList(object state) {
    
                const int Threshold = 50;
    
                this.watchersLock.AcquireWriterLock(Timeout.Infinite);
    
                try {
    
                    if (this.watchers.Count > Threshold) {
    
                        this.watchers = new Dictionary<string, WeakReference>();
    
                    }
    
                }
    
                finally {
    
                    this.watchersLock.ReleaseWriterLock();
    
                }
    
            }
    
        }
    
    }
    
    

    3.FileContainsProvider.cs

    
    //
    
    // Copyright © Microsoft Corporation. All Rights Reserved.
    
    // This code released under the terms of the
    
    // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
    
    //
    
    using System;
    
    using System.Collections.Generic;
    
    using System.IO;
    
    using Microsoft.Web.Iis.Rewrite;
    
    public sealed class FileContainsProvider : FileBaseProvider {
    
        private List<string> values;
    
        protected override void LoadTableFromFile() {
    
            this.values = new List<string>();
    
            using (StreamReader reader = this.File.OpenText()) {
    
                string line;
    
                while ((line = reader.ReadLine()) != null) {
    
                    string trimmed = line.Trim();
    
                    if (trimmed.Length > 0) {
    
                        string value = this.IgnoreCase ? trimmed.ToLowerInvariant() : trimmed;
    
                        this.values.Add(value);
    
                    }
    
                }
    
            }
    
        }
    
        protected override string Map(string input) {
    
            string inputToLower = this.IgnoreCase ? input.ToLowerInvariant() : input;
    
            foreach (string value in this.values) {
    
                if (inputToLower.Contains(value)) {
    
                    return value;
    
                }
    
            }
    
            return string.Empty;
    
        }
    
        protected override IEnumerable<SettingDescriptor> GetAdditionalSettings() {
    
            // No additional settings.
    
            yield break;
    
        }
    
        protected override void Dispose(bool disposing) {
    
            base.Dispose(disposing);
    
        }
    
    }
    
    

    4.FileMapProvider.cs

    
    //
    
    // Copyright © Microsoft Corporation. All Rights Reserved.
    
    // This code released under the terms of the
    
    // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
    
    //
    
    using System;
    
    using System.Collections.Generic;
    
    using System.IO;
    
    using Microsoft.Web.Iis.Rewrite;
    
    public sealed class FileMapProvider : FileBaseProvider {
    
        private Dictionary<string, string> dictionary;
    
        protected override void LoadTableFromFile() {
    
            this.dictionary = new Dictionary<string, string>(this.IgnoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal);
    
            using (StreamReader reader = this.File.OpenText()) {
    
                string line;
    
                while ((line = reader.ReadLine()) != null) {
    
                    string[] keyValue = line.Split(base.Separator);
    
                    string key = keyValue[0].Trim();
    
                    if (!string.IsNullOrEmpty(key)) {
    
                        string value = keyValue.Length > 1 ? keyValue[1].Trim() : string.Empty;
    
                        this.dictionary.Add(key, value);
    
                    }
    
                }
    
            }
    
        }
    
        protected override string Map(string input) {
    
            string output;
    
            if (this.dictionary.TryGetValue(input, out output)) {
    
                return output;
    
            }
    
            return string.Empty;
    
        }
    
        protected override IEnumerable<SettingDescriptor> GetAdditionalSettings() {
    
            yield return new SettingDescriptor(SettingNames.CharSeparator, SettingNames.CharSeparatorFriendlyName);
    
        }
    
        protected override void Dispose(bool disposing) {
    
            base.Dispose(disposing);
    
        }
    
    }
    
    

    5.SettingNames.cs

    
    //
    
    // Copyright © Microsoft Corporation. All Rights Reserved.
    
    // This code released under the terms of the
    
    // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
    
    //
    
    using System;
    
    internal static class SettingNames {
    
        public const string FilePath = "FilePath";
    
        public const string FilePathFriendlyName = "File path";
    
        public const string IgnoreCase = "IgnoreCase";
    
        public const string IgnoreCaseFriendlyName = "Ignore case";
    
        public const string CharSeparator = "Separator";
    
        public const string CharSeparatorFriendlyName = "Separator character";
    
        public const string ConnectionString = "ConnectionString";
    
        public const string ConnectionStringFriendlyName = "SQL Server connection string";
    
        public const string StoredProcedure = "StoredProcedure";
    
        public const string StoredProcedureFriendlyName = "Stored procedure name";
    
        public const string CacheMinutesInterval = "CacheMinutesInterval";
    
        public const string CacheMinutesIntervalFriendlyName = "Cache minutes interval";
    
    }
    
    

    6.Resources.Designer.cs

    
    //------------------------------------------------------------------------------
    
    // <auto-generated>
    
    //     This code was generated by a tool.
    
    //     Runtime Version:4.0.30128.1
    
    //
    
    //     Changes to this file may cause incorrect behavior and will be lost if
    
    //     the code is regenerated.
    
    // </auto-generated>
    
    //------------------------------------------------------------------------------
    
    namespace Microsoft.Web.Iis.Rewrite.Providers {
    
        using System;
    
       
    
        
    
        /// <summary>
    
        ///   A strongly-typed resource class, for looking up localized strings, etc.
    
        /// </summary>
    
        // This class was auto-generated by the StronglyTypedResourceBuilder
    
        // class via a tool like ResGen or Visual Studio.
    
        // To add or remove a member, edit your .ResX file then rerun ResGen
    
        // with the /str option, or rebuild your VS project.
    
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
    
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    
        [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    
        internal class Resources {
    
           
    
            private static global::System.Resources.ResourceManager resourceMan;
    
           
    
            private static global::System.Globalization.CultureInfo resourceCulture;
    
           
    
            [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    
            internal Resources() {
    
            }
    
           
    
            /// <summary>
    
            ///   Returns the cached ResourceManager instance used by this class.
    
            /// </summary>
    
            [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
    
            internal static global::System.Resources.ResourceManager ResourceManager {
    
                get {
    
                    if (object.ReferenceEquals(resourceMan, null)) {
    
                        global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Web.Iis.Rewrite.Providers.Resources", typeof(Resources).Assembly);
    
                        resourceMan = temp;
    
                    }
    
                    return resourceMan;
    
                }
    
            }
    
           
    
            /// <summary>
    
            ///   Overrides the current thread's CurrentUICulture property for all
    
            ///   resource lookups using this strongly typed resource class.
    
            /// </summary>
    
            [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
    
            internal static global::System.Globalization.CultureInfo Culture {
    
                get {
    
                    return resourceCulture;
    
                }
    
                set {
    
                    resourceCulture = value;
    
                }
    
            }
    
           
    
            /// <summary>
    
            ///   Looks up a localized string similar to Rewrite file provider exception. The file &quot;{0}&quot; does not exist..
    
            /// </summary>
    
            internal static string FilePathDoesNotExistFormat {
    
                get {
    
                    return ResourceManager.GetString("FilePathDoesNotExistFormat", resourceCulture);
    
                }
    
            }
    
           
    
            /// <summary>
    
            ///   Looks up a localized string similar to The rewrite provider requires the setting &quot;{0}&quot;..
    
            /// </summary>
    
            internal static string ProviderSettingExpectedFormat {
    
                get {
    
                    return ResourceManager.GetString("ProviderSettingExpectedFormat", resourceCulture);
    
                }
    
            }
    
        }
    
    }
    
    

    7.Resources.resx

    
    <?xml version="1.0" encoding="utf-8"?>
    
    <root>
    
      <!--
    
        Microsoft ResX Schema
    
        
    
        Version 2.0
    
       
    
        The primary goals of this format is to allow a simple XML format
    
        that is mostly human readable. The generation and parsing of the
    
        various data types are done through the TypeConverter classes
    
        associated with the data types.
    
       
    
        Example:
    
       
    
        ... ado.net/XML headers & schema ...
    
        <resheader name="resmimetype">text/microsoft-resx</resheader>
    
        <resheader name="version">2.0</resheader>
    
        <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    
        <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    
        <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    
        <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    
        <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
    
            <value>[base64 mime encoded serialized .NET Framework object]</value>
    
        </data>
    
        <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    
            <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
    
            <comment>This is a comment</comment>
    
        </data>
    
                   
    
        There are any number of "resheader" rows that contain simple
    
        name/value pairs.
    
       
    
        Each data row contains a name, and value. The row also contains a
    
        type or mimetype. Type corresponds to a .NET class that support
    
        text/value conversion through the TypeConverter architecture.
    
        Classes that don't support this are serialized and stored with the
    
        mimetype set.
    
       
    
        The mimetype is used for serialized objects, and tells the
    
        ResXResourceReader how to depersist the object. This is currently not
    
        extensible. For a given mimetype the value must be set accordingly:
    
       
    
        Note - application/x-microsoft.net.object.binary.base64 is the format
    
        that the ResXResourceWriter will generate, however the reader can
    
        read any of the formats listed below.
    
       
    
        mimetype: application/x-microsoft.net.object.binary.base64
    
        value   : The object must be serialized with
    
                : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
    
                : and then encoded with base64 encoding.
    
       
    
        mimetype: application/x-microsoft.net.object.soap.base64
    
        value   : The object must be serialized with
    
                : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
    
                : and then encoded with base64 encoding.
    
        mimetype: application/x-microsoft.net.object.bytearray.base64
    
        value   : The object must be serialized into a byte array
    
                : using a System.ComponentModel.TypeConverter
    
                : and then encoded with base64 encoding.
    
        -->
    
      <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    
        <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    
        <xsd:element name="root" msdata:IsDataSet="true">
    
          <xsd:complexType>
    
            <xsd:choice maxOccurs="unbounded">
    
              <xsd:element name="metadata">
    
                <xsd:complexType>
    
                  <xsd:sequence>
    
                    <xsd:element name="value" type="xsd:string" minOccurs="0" />
    
                  </xsd:sequence>
    
                  <xsd:attribute name="name" use="required" type="xsd:string" />
    
                  <xsd:attribute name="type" type="xsd:string" />
    
                  <xsd:attribute name="mimetype" type="xsd:string" />
    
                  <xsd:attribute ref="xml:space" />
    
                </xsd:complexType>
    
              </xsd:element>
    
              <xsd:element name="assembly">
    
                <xsd:complexType>
    
                  <xsd:attribute name="alias" type="xsd:string" />
    
                  <xsd:attribute name="name" type="xsd:string" />
    
                </xsd:complexType>
    
              </xsd:element>
    
              <xsd:element name="data">
    
                <xsd:complexType>
    
                  <xsd:sequence>
    
                    <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
    
                    <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
    
                  </xsd:sequence>
    
                  <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
    
                  <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
    
                  <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
    
                  <xsd:attribute ref="xml:space" />
    
                </xsd:complexType>
    
              </xsd:element>
    
              <xsd:element name="resheader">
    
                <xsd:complexType>
    
                  <xsd:sequence>
    
                    <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
    
                  </xsd:sequence>
    
                  <xsd:attribute name="name" type="xsd:string" use="required" />
    
                </xsd:complexType>
    
              </xsd:element>
    
            </xsd:choice>
    
          </xsd:complexType>
    
        </xsd:element>
    
      </xsd:schema>
    
      <resheader name="resmimetype">
    
        <value>text/microsoft-resx</value>
    
      </resheader>
    
      <resheader name="version">
    
        <value>2.0</value>
    
      </resheader>
    
      <resheader name="reader">
    
        <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
    
      </resheader>
    
      <resheader name="writer">
    
        <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
    
      </resheader>
    
      <data name="FilePathDoesNotExistFormat" xml:space="preserve">
    
        <value>Rewrite file provider exception. The file "{0}" does not exist.</value>
    
      </data>
    
      <data name="ProviderSettingExpectedFormat" xml:space="preserve">
    
        <value>The rewrite provider requires the setting "{0}".</value>
    
      </data>
    
    </root>
    
    

    请注意所有文件的文件名和后缀名。

    User's image


    如果答案是正确的解决方案,请点击“接受答案”并投赞成票。如果您对此答案有其他问题,请点击“评论”。

    注意:如果您想接收此线程的相关电子邮件通知,请按照我们的 文档 中的步骤启用电子邮件通知。

    Best Regards

    Xudong Peng

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. MS XIE 40 Reputation points
    2024-10-24T13:07:11.8466667+00:00

    非常感谢老师的指导!

    我的主要目的如下,注意代码中加粗的文字

    <rule name="RequestBlockingRule2" stopProcessing="true">

    <match url=".*" />

    <conditions>

    <add input="{HTTP_USER_AGENT}" pattern="这里可以获取记事本中的每行字符串" />

    </conditions>

    <action type="CustomResponse" statusCode="403" />

    </rule>

    请问web.config有没有其他简单的方法获取记事本的字符串(关键词列表)?

    比如通过系统变量?试过,但是好像不能变成引用值。因为你们的是 规则匹配,不能灵活调用。

    FileContainsProvider 从文本文件中读取字符串集这个功能是一个非常 实用的功能,因为每次输入大量的**User-Agent或者重写映射都经常需要更新列表,如果每次修改web.config会带来误操作的风险,没有直接修改 记事本 文件内的列表安全方便。**所以还请官方考虑以后在重写安装程序URL 重写模块 2.0中增加此功能。目前的重写功能都基于固定参数值,不能灵活调用。

    因为我是代码文盲,这次的代码我等有时间再研究了,我想我应该下载Microsoft Visual Studio 2008才可以按照说明文档一步一步的做了。Microsoft Visual Studio 2008我根本就没有接触过,所以需要时间研究。

    再次感谢老师的指导!谢谢老师!

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.