3

私は経験豊富な.NETプログラマーですが、このWebプログラミング全体に不慣れです。私のASP.NETMVCWebサイトには、コントローラーコードによって動的に検出される条件下で非表示にしたいコンテンツ(ページ上部のメニューリンク)を含むグローバルレイアウトがあります。

私の傾向(これまでに学んだツールを使用する単純なアプローチ)は、ブール値のHideGlobal値をViewBagに押し込み、@内に非表示にするグローバルマークアップを_Layout.cshtmlに配置することです。 if(ViewBag.HideGlobal){}ブロック。

これが「適切な」方法であるかどうか、またはまだ明らかではない理由で使用する必要があるかみそりの魔法があるかどうかを知りたいだけです。

4

3 に答える 3

8

アクションによって返されるビューの外でアクションのビューモデルを使用するのは嫌いです。このシナリオでベースビューモデルを使用すると、非常に不格好に感じます。

グローバルメニューの表示方法を指定するロジックを含む別の(子)アクションを使用する方が、よりクリーンでわかりやすいと思います。このアクションは、グローバルメニュービューを返します。レイアウトページからそのアクションを呼び出します。

または、メニューの状態が決定されるヘッダー全体に対してアクションを作成することも、if/elseを実行してグローバルメニューの部分ビューをレンダリングすることもできます。

以下の例は、ヘッダー/グローバルメニューのニーズをカプセル化し、コードインフラストラクチャ(ベースビューモデル)への影響を最小限に抑えてヘッダー/メニューを変更する将来の証拠となる方法を提供します。

〜/ Controllers / LayoutController.cs

public class LayoutController : Controller
{
    [ChildActionOnly]
    public ActionResult Header()
    {
        var model = new HeaderViewModel();
        model.ShowGlobalMenu = ShowGobalMenu();

        return View(model);
    }
}

〜/ Views / Layout / Header.cshtml

@model HeaderViewModel
@{
    Layout = "";
}

<header>
    <a href="/">Home</a>

    @if(Model.ShowGlobalMenu)
    {
        <ul>
            <li><a href="#">Link</a></li>
            <li><a href="#">Link</a></li>
            <li><a href="#">Link</a></li>
            <li><a href="#">Link</a></li>
        </ul>
    }
</header>

〜/ Views / Shared / _Layout.cshtml

<html>
    <body>
        @Html.Action("Header", "Layout")

        <p>Stuff</p>
    </body>
</body>
于 2012-12-11T23:40:52.000 に答える
3

あなたが説明したこと(ViewBagにブール値を入れる)はうまく機能します。しかし、個人的には、強く型付けされたモデルエクスペリエンスが好きなので、マスター/レイアウトページ(ほとんどの場合)で説明しているようなUIロジックが必要な場合は、それらのフラグをベースモデルに配置することを好みます。私の他のモデルが継承している。

public class BaseModel
{
     public bool HideGlobal { get; set; }
}

そして、_Layout.cshtmlページの上部で、BaseModelを期待していることを指定します。

@model Company.Project.BaseModel

もちろん、他のビューでは他のモデルタイプが必要になる場合がありますが、このレイアウトを使用している場合、それらのモデルタイプはBaseModelから派生する必要があります。

最後に、ViewBagに不思議な、文書化されていないフィールドを表示するのではなく、フラグを確認したい場合、モデルの素敵なインテリセンスと心地よい強いタイプのメンバーがあります。

@if (!Model.HideGlobal)
{
    <div>...</div>
}

編集:BaseModelのフィールドにデータを入力するのが仕事であるベースコントローラーもあると便利な場合が多いことを付け加えておきます。鉱山は通常次のようになります。

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result != null)
        {
            var baseModel = result.Model as BaseModel;
            if (baseModel != null)
            {
                //Set HideGlobal and other BaseModel properties here
            }
        }
    }
}

ここでの最初の答えは、優しくしてください:-)

于 2012-12-11T22:53:05.720 に答える
2

このタイプのものは通常、ユーザー権限に基づいており、ベースコントローラーではなくアクションフィルターの方がはるかに優れています。

はい、ViewDataまたはを使用する必要ViewBagがありますが、実際にはビュー/モデルの一部ではなく、_layout.cshtmlの上位にあります。

アクションフィルター

public class UserAccessAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting( ActionExecutingContext filterContext ) {
        var hasAccessToMenu = /* Code */;

        filterContext.Controller.ViewData["GlobalVisible"] = hasAccessToMenu;
    }
}

表示(_layout.cshtml)

@if(ViewData["GlobalVisible"])
{
    <ul>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
    </ul>
}

これにより、このロジックをコントローラーから分離できるという利点が得られます。これはグローバルであるため重要です。

またViewData、私は私の例で使用しましたが、使用することViewBagも同様に良いです。

于 2012-12-12T00:03:34.500 に答える