5

現在、次のようなフォルダー構造があります。

Area (folder)
 - Toolkit (folder)
    - Controllers (folder)
        - AdminController.cs
    - Views (folder)
        - Admin (folder)
           - Privledges (folder)
              - Create.cshtml
              - Edit.cshtml
              - Delete.cshtml

翻訳すると

/Toolkit/{controller}/{action}/{tool}/{id}

アクションに渡された文字列 {tool} パラメーターとパラメーター {id} に基づいてビューを提供するコントローラーのように動作するようにアクションを設定するのは悪い習慣ですか?

私が話していることの実装:

    private const string FOLDER_PRIVILEGES = "./Privileges/";

    public ActionResult Privileges(string tool, string id = "")
    {
        dynamic viewModel = null;
        ToolViews view; // enum for the views
        // Parse the tool name to get the enum representation of the view requested
        bool isParsed = Enum.TryParse(tool, out view);

        if (!isParsed)
        {
            return HttpNotFound();
        }

        switch (view)
        {
            case ToolViews.Index:
                viewModel = GetIndexViewModel(); // call a function that gets the VM
                break;
            case ToolViews.Edit:
                viewModel = GetEditViewModelById(int.Parse(id)); // sloppy parse
                break;
            default:
                viewModel = GetIndexViewModel();
                break;
        }
        // The folder path is needed to reach the correct view, is this bad?
        // Should I just create a more specific controller even though it would
        // require making about 15-20 controllers?
        return View(FOLDER_PRIVILEGES + tool, viewModel);
    }

ビューを作成するときは、パス名がフォルダーに使用されていることを確認する必要があります

@Html.ActionLink("Edit", "./Toolkit/Admin/Priveleges/Edit", "Admin", new { id = item.id })

フォルダー構造がまったく変更された場合、多くのメンテナンスが必要になるため、これは不適切な方法のようです。

ただし、アクションをコントローラーに分割する必要がある場合は、それらの多くが存在します (ほぼ 20 で、時間の経過とともにさらに追加されます)。

私がやっていることが悪い習慣である場合、このようなルートを提供するための最良の方法は何ですか?

/Toolkit/Admin/Privileges/Edit/1

次のことは避けたいです。

/Toolkit/Admin/CreatePrivileges/1
/Toolkit/Admin/EditPrivileges/1
/Toolkit/Admin/DeletePrivileges/1

この質問を言葉にするのに苦労しているので、意味が分からない場合はお知らせください。

4

2 に答える 2

1

元の質問への回答ではありませんが、OP は、各アクションで列挙型をチェックするのではなく、列挙型制約のサンプルを要求しました。すなわち:

// Parse the tool name to get the enum representation of the view requested
bool isParsed = Enum.TryParse(tool, out view);

if (!isParsed)
{
    return HttpNotFound();
}

列挙型の値 (この場合はツール) を文字列として受け入れる代わりに、適切な列挙型として既にキャストされている値を強制的にアクションに入れることができます。これに対する追加の利点は、HttpNotFoundこの場合、MVC フレームワークが正しい応答 ( ) を返すことを処理することです。

これが制約方法です。あらゆるタイプの Enum を受け入れます。Enum ごとに個別の制約を作成する必要はありません。

public class EnumConstraint<T> : IRouteConstraint where T : struct
{
    private readonly HashSet<string> enumNames;
    public EnumConstraint()
    {
        string[] names = Enum.GetNames(typeof(T));
        this.enumNames = new HashSet<string>(from name in names select name.ToLowerInvariant());
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return this.enumNames.Contains(values[parameterName].ToString().ToLowerInvariant());
    }

}

次に、RegisterRoutesメソッド (MVC4) または global.asax.cs ページ (MVC3) で、次のようにルートを登録するだけです。

routes.MapRoute(
    url: "/Toolkit/Admin/{Action}/{id}",
    constraints: new { Action = new EnumConstraint<ToolViews>(), id = @"\d+" }
);

idまた、パラメーターに数の制約を追加して、それを解析する必要がないようにしました。

それがどのように機能するか教えてください。

于 2012-11-13T18:30:07.093 に答える
1

本来の意図に反する慣習をMVCに強制しようとしていると思います。

MVC では、コントローラーは名詞であり、アクションは動詞です。あなたの例を使用すると、次のようになります。

  • ツールキット (名詞) - エリア
    • 管理者 (名詞?) - サブエリア? <-- これは少しファンキーなものです
      • 特権 (名詞) - コントローラー
        • 作成 (動詞) - アクション
        • 編集 (動詞) - アクション
        • 削除 (動詞) - アクション

このように、Toolkit + Admin を領域 + サブ領域と見なすか、それらを 1 つの領域 (TookitAdmin) にまとめることができれば、コントローラーとアクションの本来の目的に戻ることができます。

コメントに基づいて、この方法に進むことに決めたようです。しかし、あなたが遠回しにたどり着いた結論は、MVC のルーツに立ち返ることだということを指摘しておきたいと思います。

補足として、MVC4 への移行を検討しましたか? そのWeb APIは、RESTful API のより優れたサポートを提供します。

于 2012-11-13T14:52:06.777 に答える