0

私が構築しているアプリケーションの 1 つで、データベース内の製品を記述するための非常に柔軟な属性ベースのシステムを構築しました。このシステムでは、各製品に不特定の数の属性を割り当てることができ、各属性は単一の「タイプ」を持つことができます。たとえば、1 つの属性タイプが「Category」で、1 つの属性に割り当てられる値は「Trucks」のようになります。特定の製品に割り当てられる属性の数に制限はありません。また、属性と属性タイプは製品とともにデータベースに保存されるため、私のアプリケーションはそれらが何であるかを事前に知りません。

特定の属性タイプのオプションの機能の 1 つは、「検索可能」かどうかです。属性が検索可能である場合、その値をタイプ名と組み合わせて使用​​して、製品を検索/フィルタリングできます。たとえば、ユーザーは、属性タイプ「Category」が「Trucks」に等しく、属性タイプ「Color」が「Red」に等しいすべての製品を返すことができます。そこにはあまりにもユニークなものはありません。

私が対処している問題は、システムが属性の型名が何であるかを事前に認識していないため、string categoryまたはのような読み取り可能な形式でパラメーターを受け入れるアクション メソッドを簡単に作成できないことですstring color。解決策として、ディクショナリへのバインディングに対する DefaultModelBinder のサポートを利用しました。このアプローチでは、フィールド名を正しい構造でフォーマットするだけでよく、アクション メソッドはIDictionary<string,string> parameters. これはすべてかなりうまく機能しますが、ユーザーが単一のパラメーターでリンクベースのフィルターを実行している場合、つまり「カテゴリ トラックの製品をもっと見る」など、非常に厄介な URL が発生します。DefaultModelBinder をディクショナリにバインドするには、フィールドの命名パターンが次のようになっている必要があります。

<input type="hidden" name="parameters[0].Key" value="Category" />
    <select name="parameters[0].Value">
    <option value="Trucks">Trucks</option>
    <option value="Compacts">Compacts</option>
    <option value="SUVs">SUVs</option>
</select>
<input type="hidden" name="parameters[1].Key" value="Manufacturer" />
<select name="parameters[1].Value">
    <option value="Ford">Ford</option>
    <option value="Toyota">Toyota</option>
    <option value="Honda">Honda</option>
</select>

これは信じられないほど冗長であるだけでなく、各キー/値のフィールド名に序数インデックスが含まれている必要があるため、ややイライラします。これは POST フォームでは許容されますが、GET URL では特に理想的ではありません?parameters[0].Key=Category&parameters[0].Value=Trucks&parameters[1].Key=Manufacturer&parameters[1].Value=Ford。これは醜いだけでなく、URL を変更すると結果セット全体が破壊される可能性があるため、実装が非常に制限されています (ユーザーが URL を変更して 2 番目のパラメーターだけで検索したい場合は、最初のパラメーターを削除する必要があります)。コレクション全体の番号を適切に付け直します)。

私が探しているのは、この種の状況を処理するためのより良い方法です。理想的には、単純にクエリ文字列の値?Category=Redを取得し、それに応じてフィルター処理したいのですが、アクション メソッドは、バインドする "Category" パラメーターが実際に存在するかどうかを知りません。このようなひどい URL 構造を作成しない、よりクリーンなクエリ文字列パラメーターを使用できるようにする間に何かありますか?

独自のカスタム ModelBinder を作成することも考えていましたが、別の方法があれば避けたいと思います。

4

1 に答える 1

2

私はあなたの「クリーンな」URIをとても好みます: ?Category=Red. それでは、そこから始めて、どのように機能するか見てみましょう。

実行時にすべてのカテゴリをロードできますよね? 私の頭の上から:

IEnumerable<string> allCategories = Categories.GetAll();
var usedCategories = Request.QueryString.AllKeys.Intersect(allCategories);
var search = from c in usedCategories
             select new 
             {
                 Key = c,
                 Value = Request.QueryString[c]
             };

これをそのまま使用することも、カスタム モデル バインダーを作成することもできます。どちらの場合も、多くのコードではありません。

于 2010-07-14T17:56:12.000 に答える