11

に次の<httpErrors>コレクションがあるとしweb.configます。

<httpErrors>
</httpErrors>

ええ、ナイス 'n 空です。

IIS 7 では、HTTP エラー ページは次のようになります。

httpエラー

美しい!(404 を強調表示したのは、これがすぐに使用する例だからです)。

ここで、次のコードを実行します。

errorElement["statusCode"] = 404;
errorElement["subStatusCode"] = -1;
errorElement["path"] = "/404.html";
httpErrorsCollection.Add(errorElement);

素晴らしい。私は今、期待どおりにこれを持っていますweb.config:

<httpErrors>
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/404.html" />
</httpErrors>

これ以上ないほど幸せです。さて、IIS 7 では、私の HTTP エラー セクションは、予想どおり、次のようになります。 代替テキスト

この時点で、人生はこれ以上に甘くありません。ここで、プログラムを使用して 404 エラーを元のスクリーンショットに示されている状態に戻したいと考えています。ロジックはremove、新しいエラーが発生する必要があることを示しています。

httpErrorsCollection.Remove(errorElement);

しかし、悲しいことに、これを行うと、私のweb.config見た目は次のようになります。

    <httpErrors>
        <remove statusCode="404" subStatusCode="-1" />
    </httpErrors>

私のIISは次のようになります。

代替テキスト

これは私のせいで予想されますweb.configが、IIS 7 API を使用してすべての有用な要素を完全ServerManagerに削除し、元に戻す方法は次のとおりです。httpErrorweb.config

<httpErrors>
</httpErrors>

何か案は?

4

3 に答える 3

21

管理セクションの下のIIS7以降では、 Configuration Editorという名前のアイコンが表示され、 ダブルクリックして展開します

system.webserver-->webdav-->httpErrors

下のDefault pathを右クリックします。

セクション --> [親に戻す] をクリックします

その後、ウェブサイトを再起動します

変更は元に戻されます

于 2012-12-17T09:30:27.853 に答える
5

私は前にこれにぶつかった。これを機能させる唯一の方法は、変更を加える前にセクションを呼び出しRevertToParent()system.webServer/httpErrors変更をコミットすることでした。

ConfigurationSection httpErrorsSection = 
           config.GetSection("system.webServer/httpErrors");

// Save a copy of the errors collection first (see pastebin example)
 httpErrorsCollectionLocal = 
            CopyLocalErrorCollection(httpErrorsSection.GetCollection()
            .Where(e => e.IsLocallyStored)
            .ToList<ConfigurationElement>());

httpErrorsSection.RevertToParent();
serverManager.CommitChanges();

RevertToParent() is called because the errors collection remains intact untilCommitChanges()` が呼び出された後にコミットする必要があります。

次に、保存されたローカル エラー コレクションのコピーを再度追加し、カスタム エラーが再追加されたときにそれを削除または更新する必要があります。

以下に完全な動作例を貼り付けました。コードはサイトのルートで動作しweb.configますが、少し手を加えるだけでweb.config、サブフォルダー内のファイルのサポートを追加できます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Web.Administration;

namespace IIS7_HttpErrorSectionClearing
{
  class Program
  {
    static void Main(string[] args)
    {
      long siteId = 60001;

      // Add some local custom errors
      CustomErrorManager.SetCustomError(siteId, 404, -1, ResponseMode.File, @"D:\websites\60001\www\404.html");
      CustomErrorManager.SetCustomError(siteId, 404, 1, ResponseMode.File, @"D:\websites\60001\www\404-1.html");
      CustomErrorManager.SetCustomError(siteId, 404, 5, ResponseMode.File, @"D:\websites\60001\www\404-5.html");

      // Change existing local custom error
      CustomErrorManager.SetCustomError(siteId, 404, 1, ResponseMode.ExecuteURL, "/404-5.aspx");

      // Revert to inherited
      CustomErrorManager.RevertCustomError(siteId, 404, 5);
      CustomErrorManager.RevertCustomError(siteId, 404, -1);
      CustomErrorManager.RevertCustomError(siteId, 404, 1);
    }
  }

  public enum ResponseMode
  {
    File,
    ExecuteURL,
    Redirect
  }  

  public static class CustomErrorManager
  {
    public static void RevertCustomError(long siteId, int statusCode, int subStatusCode)
    {
      List<Error> httpErrorsCollectionLocal = CopyLocalsAndRevertToInherited(siteId);
      int index = httpErrorsCollectionLocal.FindIndex(e => e.StatusCode == statusCode && e.SubStatusCode == subStatusCode);
      if(index > -1)
      {
        httpErrorsCollectionLocal.RemoveAt(index);
      }
      PersistLocalCustomErrors(siteId, httpErrorsCollectionLocal);
    }

    public static void SetCustomError(long siteId, long statusCode, int subStatusCode, 
                                          ResponseMode responseMode, string path)
    {
      SetCustomError(siteId, statusCode, subStatusCode, responseMode, path, null);
    }

    public static void SetCustomError(long siteId, long statusCode, int subStatusCode, 
                                          ResponseMode responseMode, string path, string prefixLanguageFilePath)
    {
      List<Error> httpErrorsCollectionLocal = CopyLocalsAndRevertToInherited(siteId);
      AddOrUpdateError(httpErrorsCollectionLocal, statusCode, subStatusCode, responseMode, path, prefixLanguageFilePath);
      PersistLocalCustomErrors(siteId, httpErrorsCollectionLocal);
    }

    private static void PersistLocalCustomErrors(long siteId, List<Error> httpErrorsCollectionLocal)
    {
      using (ServerManager serverManager = new ServerManager())
      {
        Site site = serverManager.Sites.Where(s => s.Id == siteId).FirstOrDefault();
        Configuration config = serverManager.GetWebConfiguration(site.Name);
        ConfigurationSection httpErrorsSection = config.GetSection("system.webServer/httpErrors");
        ConfigurationElementCollection httpErrorsCollection = httpErrorsSection.GetCollection();

        foreach (var localError in httpErrorsCollectionLocal)
        {
          ConfigurationElement remove = httpErrorsCollection.CreateElement("remove");
          remove["statusCode"] = localError.StatusCode;
          remove["subStatusCode"] = localError.SubStatusCode;
          httpErrorsCollection.Add(remove);

          ConfigurationElement add = httpErrorsCollection.CreateElement("error");
          add["statusCode"] = localError.StatusCode;
          add["subStatusCode"] = localError.SubStatusCode;
          add["responseMode"] = localError.ResponseMode;
          add["path"] = localError.Path;
          add["prefixLanguageFilePath"] = localError.prefixLanguageFilePath;
          httpErrorsCollection.Add(add);
        }
        serverManager.CommitChanges();
      }
    }

    private static List<Error> CopyLocalsAndRevertToInherited(long siteId)
    {
      List<Error> httpErrorsCollectionLocal;
      using (ServerManager serverManager = new ServerManager())
      {
        Site site = serverManager.Sites.Where(s => s.Id == siteId).FirstOrDefault();
        Configuration config = serverManager.GetWebConfiguration(site.Name);
        ConfigurationSection httpErrorsSection = config.GetSection("system.webServer/httpErrors");
        ConfigurationElementCollection httpErrorsCollection = httpErrorsSection.GetCollection();

        // Take a copy because existing elements can't be modified.
        httpErrorsCollectionLocal = CopyLocalErrorCollection(httpErrorsSection.GetCollection()
                                      .Where(e => e.IsLocallyStored).ToList<ConfigurationElement>());

        httpErrorsSection.RevertToParent();

        // Have to commit here because RevertToParent won't clear the collection until called.
        serverManager.CommitChanges();
        return httpErrorsCollectionLocal;
      }
    }

    private static List<Error> CopyLocalErrorCollection(List<ConfigurationElement> collection)
    {
      List<Error> errors = new List<Error>();
      foreach (var error in collection)
      {
        errors.Add(new Error()
        {
          StatusCode = (long)error["statusCode"],
          SubStatusCode = (int)error["subStatusCode"],
          ResponseMode = (ResponseMode)error["responseMode"],
          Path = (string)error["path"],
          prefixLanguageFilePath = (string)error["prefixLanguageFilePath"]
        });
      }
      return errors;
    }

    private static void AddOrUpdateError(List<Error> collection, long statusCode, int subStatusCode, 
                                             ResponseMode responseMode, string path, string prefixLanguageFilePath)
    {
      // Add or update error
      Error error = collection.Find(ce => ce.StatusCode == statusCode && ce.SubStatusCode == subStatusCode);
      if (error == null)
      {
        collection.Add(new Error()
        {
          StatusCode = statusCode,
          SubStatusCode = subStatusCode,
          ResponseMode = responseMode,
          Path = path,
          prefixLanguageFilePath = prefixLanguageFilePath
        });
      }
      else
      {
        error.ResponseMode = responseMode;
        error.Path = path;
        error.prefixLanguageFilePath = prefixLanguageFilePath;
      }
    }

    private class Error
    {
      public long StatusCode { get; set; }
      public int SubStatusCode { get; set; }
      public ResponseMode ResponseMode { get; set; }
      public string Path { get; set; }
      public string prefixLanguageFilePath { get; set; }
    }  
  }
}
于 2010-11-24T22:15:35.813 に答える
0

さて、これは私がこの問題について見つけたものです:

ServerManager serverManager = new ServerManager();
Configuration config = serverManager.GetWebConfiguration(siteName);
ConfigurationSection httpErrorsSection = config.GetSection("system.webServer/httpErrors");
ConfigurationElementCollection httpErrorsCollection = httpErrorsSection.GetCollection();
foreach (ConfigurationElement errorEle in httpErrorsCollection) {
    if (errorEle("statusCode") == statusCode && errorEle("subStatusCode") == subStatusCode) {
        errorEle.Delete();
        serverManager.CommitChanges();
        return;
    }
}

通常どおり要素のリストを取得し、ループして目的の要素を見つけ、その要素に対して delete を呼び出します。それだけで動作します。この質問がされたときにこれが存在したかどうかはわかりませんが、現在は存在します。そのステータス コードとサブステータス コードを把握しておく必要があります。

于 2016-06-13T22:28:53.527 に答える