14

コレクション内の項目のプロパティに対してリモート検証を実行しようとしています。検証は、コレクションの最初のアイテムで正常に機能します。検証メソッドへの http リクエストは次のようになります。

/Validation/IsImeiAvailable?ImeiGadgets[0].ImeiNumber=123456789012345

ただし、URL が以下のように見える 2 番目の項目では、検証が機能しません。

/Validation/IsImeiAvailable?ImeiGadgets[1].ImeiNumber=123456789012345

これの理由は、ゼロ インデックスで始まらないコレクションではバインドが機能しないことだと確信しています。

私の検証方法には、次のような署名があります。

public JsonResult IsImeiAvailable([Bind(Prefix = "ImeiGadgets")] Models.ViewModels.ImeiGadget[] imeiGadget)

コレクション内のアイテムを渡すので、このようにバインドする必要がありますが、実際に渡すのは単一の値です。

単純な古いクエリ文字列としてバインドする以外に、これに対処できる方法はありますか。

ありがとう

編集:これは Imei 変数を取得するための簡単な修正ですが、モデルバインディングを使用したいです:

string imeiNumber = Request.Url.AbsoluteUri.Substring(Request.Url.AbsoluteUri.IndexOf("=")+1);

編集: これが私の ImeiGadget クラスです:

public class ImeiGadget
{
    public int Id { get; set; }

    [Remote("IsImeiAvailable", "Validation")]
    [Required(ErrorMessage = "Please provide the IMEI Number for your Phone")]
    [RegularExpression(@"(\D*\d){15,17}", ErrorMessage = "An IMEI number must contain between 15 & 17 digits")]
    public string ImeiNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
}
4

5 に答える 5

8

カスタム モデル バインダーを作成できます。

public class ImeiNumberModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var modelName = bindingContext.ModelName;
        var request = controllerContext.HttpContext.Request;
        var paramName = request
            .Params
            .Keys
            .Cast<string>()
            .FirstOrDefault(
                x => x.EndsWith(modelName, StringComparison.OrdinalIgnoreCase)
            );

        if (!string.IsNullOrEmpty(paramName))
        {
            return bindingContext
                .ValueProvider
                .GetValue(request[paramName])
                .AttemptedValue;
        }

        return null;
    }
}

そして、それをコントローラー アクションに適用します。

public ActionResult IsImeiAvailable(
    [ModelBinder(typeof(ImeiNumberModelBinder))] string imeiNumber
)
{
    return Json(!string.IsNullOrEmpty(imeiNumber), JsonRequestBehavior.AllowGet);
}

これで、そのImeiGadgets[xxx]部分はクエリ文字列から無視されます。

于 2012-05-29T14:53:01.273 に答える
0

検証のために単一の値をサーバーに送信する場合、アクション メソッドは、コレクションではなく、スカラー (単一値) パラメーターのみを受け入れる必要があります。URL は次のようになります ({controller}/{action}/{id} のデフォルトのルーティング テーブルを仮定すると:

/Validation/IsImeiAvailable?ImeiNumber=123456789012345

対応するアクション メソッドのシグネチャは次のようになります。

/* note that the param name has to matchthe prop name being validated */
public ActionResult IsImeiAvailable(int ImeiNumber)

編集: 特定の ID が利用可能かどうかを調べるために使用できます。

パラメータの名前を変更したい場合は、ルーティング テーブルを変更できますが、それは別のトピックです。

簡単に言うと、 のコレクションを検証したい場合は、そのコレクションImeiGadget全体を GET または POST する必要があります。単一の値の場合、送信したり、コレクション全体を期待したりすることはあまり意味がありません。

更新: 新しい情報に基づいて、リモート検証属性が配置されている場所を調べます。次のように、のようなものに配置される可能性があるように聞こえIEnumerable<IMEiGadgets>ます。

[Remote("IsImeiAvailable", "Validation", "'ImeiNumber' is invalid"]
public IEnumerable<ImeiGadget> ImeiGadgets { get; set;}

その属性を移動し、ImeiGadget代わりにクラスにあるように変更して、このようにすることは可能でしょうか?

[Remote("IsImeiAvailable", "Validation", "'ImeiNumber is invalid"]
public int ImeiNumber { get; set;}

理論的には、上記の私の回答で提案されている変更も行う場合、これを機能させるために HTML テンプレートまたはスクリプトを変更する必要はありません。理論的には。

于 2012-05-29T13:33:09.547 に答える
0

多くの場所でこのバインド機能が必要で、IsImeiAvailable検証方法を制御しない限り、カスタム モデル バインダーの作成はオーバーヘッドになると思います

このような簡単な解決策を試してみませんか?

// need little optimization?
public JsonResult IsImeiAvailable(string imeiNumber)
{
  var qParam = Request.QueryString.Keys
     .Cast<string>().FirstOrDefault(a => a.EndsWith("ImeiNumber"));

  return Json(!string.IsNullOrEmpty(imeiNumber ?? Request.QueryString[qParam]), JsonRequestBehavior.AllowGet);
}
于 2012-05-31T06:15:41.640 に答える
0

コレクション全体を投稿しているが、連続していないインデックスがある場合は、代わりに辞書にバインドすることを検討でき ます http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

単一のアイテムのみを投稿するか、GET リンクを使用している場合は、次のように修正する必要があります。

/Validation/IsImeiAvailable?ImeiNumber=123456789012345

public JsonResult IsImeiAvailable(string imeiNumber)
于 2012-05-29T14:11:59.910 に答える