24

カスタムモデルバインダーで要求コンテキストを手動で確認したり、投稿されたファイルのみを入力として受け取る別のアクションメソッドを作成したりせずに、投稿されたファイル(<input type="file" />)をASP.NET MVCのモデルバインディングに参加させる方法はありますか?

私はこれがうまくいくと思っていたでしょう:

class MyModel {
  public HttpPostedFileBase MyFile { get; set; }
  public int? OtherProperty { get; set; }
}

<form enctype="multipart/form-data">
  <input type="file" name="MyFile" />
  <input type="text" name="OtherProperty" />
</form>

public ActionResult Create(MyModel myModel) { ... } 

しかし、上記のシナリオを考えるMyFileと、バインディングコンテキストの値プロバイダー値の一部でさえありません。OtherPropertyもちろんです。)しかし、これを行うと機能します。

public ActionResult Create(HttpPostedFileBase postedFile, ...) { ... } 

では、パラメーターがモデルの場合、なぜバインディングが発生しないのでしょうか。また、どうすればそれを機能させることができますか?カスタムモデルバインダーを使用しても問題はありませんが、カスタムモデルバインダーでこれを確認せずに行うにはどうすればよいRequest.Files["MyFile"]ですか?

一貫性、明確性、テスト容易性のために、リクエストコンテキストを手動で検査することなく、投稿されたファイルにバインドされたプロパティを含む、モデル上のすべてのプロパティの自動バインドをコードで提供したいと思います。私は現在、ScottHanselmanが書いたアプローチを使用してモデルバインディングをテストしています。

それとも私はこれを間違った方法で行っていますか?これをどのように解決しますか?または、Request.FormとRequest.Filesの分離の歴史があるため、これは設計上不可能ですか?

4

4 に答える 4

29

その理由は、 のみをValueProviderDictionary検索しRequest.Form、モデル バインディング コンテキストに値プロバイダー ディクショナリを設定するためであることが判明しました。そのため、カスタム モデル バインダーでは、リクエスト コンテキスト内のファイル コレクションを直接検査せずに、投稿されたファイルをモデル バインドに参加させることはできません。これは、同じことを達成するために私が見つけた最も近い方法です。RouteDataRequest.QueryString

public ActionResult Create(MyModel myModel, HttpPostedFileBase myModelFile) { }

myModelFileが実際に入力フォーム フィールドの名前である限り、fileカスタムのものは必要ありません。

于 2009-06-08T21:21:55.680 に答える
14

もう 1 つの方法は、入力と同じ名前の隠しフィールドを追加することです。

<input type="hidden" name="MyFile" id="MyFileSubmitPlaceHolder" />

次に、DefaultModelBinder はフィールドを認識し、正しいバインダーを作成します。

于 2009-10-29T21:39:39.923 に答える
7

あなたがリンクした投稿から(の投稿を介して...)彼がリンクしているこの投稿を見たことがありますか?

そうでなければ、それは非常に単純に見えます。これは彼が使用するモデルバインダーです:

public class HttpPostedFileBaseModelBinder : IModelBinder {
    public ModelBinderResult BindModel(ModelBindingContext bindingContext) {
        HttpPostedFileBase theFile =
            bindingContext.HttpContext.Request.Files[bindingContext.ModelName];
        return new ModelBinderResult(theFile);
    }
}

彼はそれGlobal.asax.csを次のように登録します。

ModelBinders.Binders[typeof(HttpPostedFileBase)] = 
    new HttpPostedFileBaseModelBinder();

次のようなフォームで投稿します。

<form action="/File/UploadAFile" enctype="multipart/form-data" method="post">
    Choose file: <input type="file" name="theFile" />
    <input type="submit" />
</form>

すべてのコードはブログ投稿から直接コピーされます...

于 2009-06-06T22:33:20.577 に答える
-17

カスタムバインダーを登録する必要はありませんHttpPostedFileBase。デフォルトでフレームワークに登録されます。

public ActionResult Create(HttpPostedFileBase myFile)
{
    ...
}

ブログやウェブフォーラムだけに頼るのではなく、たまに本を読むのに役立ちます。

于 2009-06-07T06:34:14.403 に答える