保存されたデータからASP.NET MVCでURL /ルートを再構築する方法はありますか?
-
05-07-2019 - |
質問
ASP.NET MVCフレームワークとその配管に不慣れなことがきっかけで、誰もが私の質問を読んで検討するのに忍耐することに感謝しています!
さて、ここにシナリオがあります。検索に基づいてデータを表示するグリッド、他のデータからドリルダウン、コンテキスト固有のデータに基づいたレポート(つまり、Fooの詳細ページにある) 、次にFoo)に関連するデータの表を示すリンクをクリックします。など
これらのページはすべてアプリ全体にあり、ユーザーは「レポート」を保存できます。または、名前と説明を指定してグリッドを作成します。これは、グリッドに表示されるデータを実際に保存するのではなく、グリッドの外観を定義するパラメーターを保存し、データの get に使用されたパラメーターを保存し、パラメーターを保存します。 " where"を定義するアプリでは、それらは(アクション、コントローラー、ルート)です-基本的には、レポート/グリッドとその作成方法に関するメタデータの束。
これらの保存されたレポートはすべて、アプリの特定のページに名前と説明を表示する単一のリストで利用できます。各リンクは、" / Reports / Saved / 248"などの汎用URLにリンクしています。 (ここで、248はレポートのIDの例です)。
ヘルプが必要な部分は次のとおりです。
URL" / Reports / Saved / 248"からアクションにアクセスしたときその特定のレポートのデータベースからメタデータを引き出すと、そのデータとリクエストを、レポートが最初に保存されたビューを表示するために使用される同じアクション、コントローラー、およびルートにリダイレクトできますか?基本的に、ユーザーは同じビューで、保存元と同じURLでレポートを表示する必要があります。可能であれば、基本的に「電話をかける」ことができれば嬉しいです。メソッド呼び出しを行っているのと同じアクション。
更新:残念ながら、レポートページ(つまり、これらのグリッドが表示されるページ)はRESTful URLを使用していません-たとえば、かなり多くの潜在的なパラメーター(約30 )選択リスト、テキストボックスなどを含むフォームから取得します。ユーザーがそのページを送信すると、モデルバインダーが作成する複雑なタイプを受け入れるアクションに対してPOSTを実行します。同じアクションを呼び出したいのですユーザーがデータベースから保存された高度な検索を選択したとき。この例は私の問題の典型です。
ありがとう
解決
RouteValueDictionaryを受け取る署名でRedirectToActionを使用したいと思うと思います。リダイレクト先のメソッドは、コントローラーのValueProviderから値をプルできる必要があります。次のようになります:
public ActionResult Saved( int id )
{
var reportParams = db.Reports.SingleOrDefault( r => r.ID == id );
if (reportParams == null)
...handle error...
var routeValues = ParamsToRouteValueDictionary( reportParams );
return RedirectToAction( reportParams.Action, reportParams.Controller, routeValues );
}
private RouteValueDictionary ParamsToRouteValueDictionary( object parameters )
{
var values = new RouteValueDictionary();
var properties = parameters.GetType().GetProperties()
.Where( p => p.Name != "Action" && p.Name != "Controller" );
foreach (var prop in properties)
{
values.Add( prop.Name, prop.GetValue(parameters,null) );
}
return values;
}
編集
メソッドのパラメーターとしてフィルターモデルを使用すると、実際に簡単になります。アクションのGETおよびPOSTバージョンが必要です。
[ActionName("People")]
[AcceptVerbs( HttpVerbs.Get )]
public ActionResult PeopleDisplay( SearchModel filter )
{
return People( filter );
}
[AcceptVerbs( HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult People( SearchModel filter )
{
....
}
次に、レポート用のdbにフィルターパラメーター(名前)、アクション(" People")、およびコントローラーを保存します。リダイレクト結果はGETを使用し、PeopleDisplayメソッドに転送されます。PeopleDisplayメソッドは、正しいパラメーターでPeopleメソッドを呼び出します。フォームから投稿すると、Peopleメソッドが直接呼び出されます。 2つの方法を使用すると、CSRF防止メカニズムを使用できます。アクセスを制限したい場合は、TempDataでフラグを使用して、GETアクションがリダイレクトメカニズムを介してのみ呼び出されるようにすることができます。
編集の終了
別の方法として、使用するビューを単に保存し、リダイレクトを行う代わりに、適切なビューをレンダリングすることもできます。考慮したいことの1つは、リダイレクトを実行すると、すべてのパラメーターを含むURLになることです。一方、ビューをレンダリングすると、URLはそのままで、レポートの作成時に使用したURLと同じビューが表示されます。 。
他のヒント
RedirectToActionメソッドを使用して、ルート値とともに、コントローラー上の特定のアクションメソッドに301リダイレクトを発行できます。
ReportMeta meta = _reportDataAccess.Get(id);
return RedirectToAction(meta.Action, meta.Controller, meta.RouteData);
これらの値は次のようなものです:
meta.Action = "Bar";
meta.Controller = "Foo";
meta.RouteData = new {
// possibly settings for the grid
start = DateTime.Min,
end = DateTime.Now,
sort = "Date"
// you get the idea
};
もちろん、これに関して私が直接目にする問題は、コントローラー/アクションメソッドが時間とともに変化したときに何が起こるかであり、レポートデータは無効になります。しかし、あなたはおそらくそれをすでに考えていたでしょう。