4

HttpPost対応するビューを返すアクション メソッドに投稿する単純なフォームがあります。私の問題は、404 Not Foundエラーが発生することです。奇妙なことに、フォーム メソッドとアクション メソッドの属性を に変更するとGET、それが機能し、TestMethod ビューが表示されます。

を使用するために何かが足りないようですPOSTが、他のコントローラーでの投稿は正常に機能します (アカウントのログインと登録など)。この属性は、承認が必要なコントローラーまたはアクションをAllowAnonymous(属性を介して) 指定するのではなく、匿名アクセスを許可するコントローラーまたはアクションを指定できるカスタム属性であることに注意してください。Authorize不可能なことはないと思いますが、それが私の問題とは何の関係もないと思います。何が間違っているかについて何か考えはありますか?

形:

@using (Html.BeginForm("TestMethod", "Test", FormMethod.Post, new { @id = "testForm" })) {
    <fieldset>
        <legend>Test Form</legend>
        <input type="submit" value="Submit" />
    </fieldset>
}

コントローラーのアクション:

[AllowAnonymous]
[HttpPost]
public ActionResult TestMethod() {
    return View();
}

見る:

<h2>TestMethod</h2>
<p>HttpPost method was successful.</p>

Global.asax.cs からのルート登録方法:

public static void RegisterRoutes(RouteCollection routes) {
        routes.IgnoreRoute("favicon.ico");
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // About
        routes.MapRoute(
            "About", // Route name
            "about", // URL with parameters
            new { controller = "Home", action = "About" } // Parameter defaults
        );

        // Faq
        routes.MapRoute(
            "Faq", // Route name
            "faq", // URL with parameters
            new { controller = "Home", action = "Faq" } // Parameter defaults
        );

        // Glossary
        routes.MapRoute(
            "Glossary", // Route name
            "glossary", // URL with parameters
            new { controller = "Home", action = "Glossary" } // Parameter defaults
        );

        // Register
        routes.MapRoute(
            "Register", // Route name
            "register", // URL with parameters
            new { controller = "Account", action = "Register" } // Parameter defaults
        );

        // LogIn
        routes.MapRoute(
            "LogIn", // Route name
            "login/{id}", // URL with parameters
            new { controller = "Account", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults
        );
        routes.MapRoute(
            "LogOn", // Route name
            "logon/{id}", // URL with parameters
            new { controller = "Account", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults
        );

        // Default
        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

}

属性コードの承認:

// AllowAnonymousAttribute class
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AllowAnonymousAttribute : Attribute { }

// GlobalAuthorize class
public sealed class GlobalAuthorize : AuthorizeAttribute {
    public override void OnAuthorization(AuthorizationContext filterContext) {
        bool skipAuthorization = 
            filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || 
            filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);

        if (!skipAuthorization) base.OnAuthorization(filterContext);
    }
}

// RedirectAuthorizeAttribute class
public class RedirectAuthorizeAttribute : AuthorizeAttribute {
    public string RedirectUrl { get; set; }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        filterContext.Result = new RedirectResult(RedirectUrl);
    }
}

グローバルフィルター:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
    filters.Add(new RequireHttpsAttribute());
    filters.Add(new GlobalAuthorize());
    filters.Add(new HandleErrorAttribute());
}

ルート書き換えルール:

<rewrite>
  <rules>
    <!-- Block all requests made to a website that do not have the host header set. -->
    <rule name="Fail bad requests" stopProcessing="true">
      <match url=".*" />
      <conditions>
        <add input="{HTTP_HOST}" pattern="localhost" negate="true" />
      </conditions>
      <action type="AbortRequest" />
    </rule>
    <!-- Remove trailing slash from all incoming requests. -->
    <rule name="Remove trailing slash" stopProcessing="false">
      <match url="(.*)/$" />
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Redirect" redirectType="Permanent" url="{R:1}" />
    </rule>
    <!-- Convert all requests to all lowercase. -->
    <rule name="Convert to lowercase" stopProcessing="false">
      <match url=".*[A-Z].*" ignoreCase="false" />
      <action type="Redirect" url="{ToLower:{R:0}}" redirectType="Permanent" />
    </rule>
    <!-- Any URL with (HTTPS == OFF) and (HTTP_HOST with colon) -> use for development testing. -->
    <rule name="Development redirect to HTTPS" enabled="true" stopProcessing="true">
      <match url=".*" ignoreCase="true" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
        <add input="{HTTPS}" pattern="^OFF$" />
        <add input="{HTTP_HOST}" pattern="([^/:]*?):[^/]*?" />
      </conditions>
      <action type="Redirect" url="https://{C:1}:44300{URL}" />
    </rule>
    <!-- Redirect any HTTP request to HTTPS. -->
    <rule name="Redirect to HTTPS" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTPS}" pattern="^OFF$" ignoreCase="true" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
    </rule>
  </rules>
</rewrite>
4

2 に答える 2

5

やっと犯人がわかった気がします。まず第一に、問題が何であったかを知った今、この質問のタイトルはあまり正確ではないことを認めます. この問題は、主に Web.config のルールの書き直しに関係していました。この質問に対する他の人のコメントに答えるまで、私はルールの書き直しを完全に忘れていました。

とにかく、問題は URL をすべて小文字に書き換えるルールでした。アカウント登録フォームとログイン フォームが正常に機能していることはわかっていたので、チェックアウトしたところ、それらのHtml.BeginFormステートメントにパラメーターがなく、小文字の URL が生成されていることがわかりました。テストメソッドに対してパラメーターなしの POST リクエストを試してみましたが、うまくいきました。次に、アクションとコントローラーのパラメーターをHtml.BeginFormステートメントで使用しようとしましたが、今回は小文字の文字列で入力しました: Html.BeginForm("testmethod", "test"...). 案の定、これも問題なく機能し、ページ ソースではフォーム アクションが小文字で表示されました。

私の問題を解決するには、POSTリクエストに一致しないように条件を設定する必要がありました: <add input="{REQUEST_METHOD}" matchType="Pattern" pattern="POST" negate="true" />. 問題は特に小文字のルールではなく、POSTリクエストがリダイレクトされていたことに注意してください。リダイレクトが s に変換されてエラーが発生するという問題について説明しているブログを見つけました。これはまさに私が経験していたことです。数年前のものですが、どうやらまだ適切な情報です。POSTGET

いずれにせよ、私は今、元気を取り戻しています。2 セントを投入してくれたすべての人に感謝します。

PS ブラウザーのタブを閉じて検索を終了するときに、この SO questionにリンクすると思いました。これは間違いなく私の問題に関連しているためです。

于 2012-08-20T21:37:57.453 に答える
0

私は今あなたのコードをテストしました。最初はHTTPSを使用していないためにリダイレクトされたため、この属性を無効にしましたが、その後、コードは機能しました。

これが私の論理的な控除です...

  • HTTPSが問題だった場合、404は取得されません。
  • ログインしていない場合は、ログインページにリダイレクトされます。

私が考えることができる唯一のことは、コントローラーの名前が「TestController」ではないか、コントローラーがエリア内にあり、このエリアに。を指定するのを忘れていることBeginFormです。たまたまこれらの一つですか?

于 2012-08-20T09:37:47.057 に答える