ASP.NET MVC-PageDataの応用

4711 ワード

一、一つの機能を実現するには、異なるページに以下の内容を配置し、ユーザーの行為情報を収集する.
<input type='hidden' id='page_id' value='xxxx' />

<script type="text/javascript">

    //balabala...

</script>


[1]需要の中にはまだ少し隠れていて、一部のページはプラスして、一部のページはプラスしない.
二、方案
シナリオ1:もちろんそうすることができます:採集する必要があるページを見つけて、一つ一つ開いて採集コードをコピーして、それからxxxxを各ページに割り当てた値に修正します.しかし、これは明らかにDRYの原則に反している.
シナリオ2:採集コードがあちこちに貼り付けられることを望まない場合は,Viewの観点からpartial viewとlayout pagesが代替メカニズムとなる.前者を使用する場合、まだ採集されるページが必要であり、採集コードを含むpartial viewを繰り返し参照します.後者を使用すると、サイトが複数のlayout pagesを使用している場合(これはよく見られる)、依然として重複した貼り付け収集コードが必要になります.
1.では、両者を結合し、paritial viewで収集コードを含め、各layout pagesでpartial viewを参照します.
@Html.Partial("_TraceByPageIdScript")


採集コードを_に安然と存在させるTraceByPageIdScriptというpartial viewにあります.
2.page_としてid値のxxxxはどうしますか?
最初のアイデアは、採集されたページの中で、ViewBag.PageIdは、変数が使用される前に値(nullではない)があることを保証する値(set)を付与します.そしてTraceByPageIdScriptではViewBagが使用できる.Pageしました(get).
実験恥ずかしい失敗鳥.
pagesのViewBagとlayout pagesのViewBagは異なるオブジェクトであり,異なるWebViewPageインスタンスに属していることが分かった.同様に、MVC 3以前のViewDataも含めて、「pagesはlayout pagesとデータを共有する必要がある」というシーンでは使われていません.[it] Gets or sets a dictionary that contains data to pass between the controller and the view. http://msdn.microsoft.com/en-us/library/system.web.mvc.viewpage.viewdata.aspx
GoogleはPageData[it]Provides array-like access to page data that is shared between pages,layout pages,and partial pagesに着いた.http://msdn.microsoft.com/en-us/library/system.web.webpages.webpagebase.pagedata(v=VS.99).aspx
だから採集コードの中のxxxxは、PageData["xxxx"]に置き換えることができます.
3.この时、一つのミスを犯したことに気づいて、ブレークポイントを见て、PageData["xxxx"]のpartial pagesの値はnullです.(これは私のMSDN注釈に対する理解とあまり一致していません)方法を変えましょう.
@Html.Partial("_TraceByPageIdScript", (int?)PageData["PageId"], new ViewDataDictionary())

注意:ここで3番目のパラメータを省略すると、nullがpartial viewに渡されると、実際に渡されるオブジェクトタイプは@modelが示すタイプであり、異常を引き起こすことになります.これはASPです.NET MVC 3の変なところは、後続バージョンが調整されているかどうかはまだ分からない.次の2つの資料は自分に解法を与えた.
  a.  http://stackoverflow.com/questions/650393/renderpartial-with-null-model-gets-passed-the-wrong-type     @Html.Partial("_TraceByPageIdScript", new ViewDataDictionary(PageData["PageId"]))

  b.  http://stackoverflow.com/questions/9292852/how-do-i-invoke-a-partial-view-with-null-for-its-model     @Html.Partial("_TraceByPageIdScript", (int?)PageData["PageId"], new ViewDataDictionary())
4.前の需要[1]が失われ、_TraceByPageIdScript.cshtmlでは、収集コードをパッケージします.
@model int?

@if(Model.HasValue)

{

    <input type='hidden' id='page_id' value='@Model.Value' />

    <script type="text/javascript">

        //balabala...

    </script>

}

三、結びの言葉
小さな紆余曲折を経て、これで完全にこの需要を実現した.
ASPを除く.NET MVCに関する知識のほか、「値すなわちスイッチ」モードの使用は、必要に応じて採集コードをロードする効果を実現し、今後他のページが採集に参加する必要がある場合は、対応するページで、値を割り当てるだけでよい.収集したページは不要で、nullに値を付けたり、値を付けた文を注視したりすればいいです.
より理想的な案は、実際には採集されたページであり、採集されるために修正する必要はありません.
方法の1つは、構成された形式で辞書を維持し、valueはpageです.id,keyは特定のページを一意に識別できることを要求する.この辞書があれば、プログラムは実行時に要求に基づいてkeyを見つけることができ、page_を見つけることができます.id.これに基づいて,layout pagesに共有できる変数を用いて,layout pagesが「出力収集コード」のスイッチをオンにするかどうかを教えることができる.
ここには2つの複雑な点があります.
  1. ここで言う共有変数としてどのベクターを使用しますか?リクエストに応じてpageを見つけることにもつながります.idのタイミング.タイミング面ではActionFilterメカニズムを考慮することができ,これにより自然にControllerとPages間の橋渡し:ViewBag/ViewDataを利用することができる.Layout pagesはそれを手に入れて、心の中できっと楽しいです.http://www.manasinc.com/setting-a-viewbag-property-in-the-onresultexecuting-action-filter-in-asp-net-mvc/
  2. 肝心な難点は、辞書のkeyの選択です.urlを使用するとrouteが変化すると、対応するページの収集が無効になります.routeを使用する場合は、パラメータの値の変化も考慮します.
この実現案の複雑さを考慮すると,開発とメンテナンスにはより多くの精力が必要であり,さらなる探索は行われていない.
P.S.PageData["XXX"]はPageに等しい.XXX